用Python小程式(失败地)简化例子的标注

在上个月的一篇部落格中,我们介绍了添加语言学例子的方法,使用的是gb4e这个package,当然大家不能忘了这个package在引导码中的顺序。还有,我们最(bì)好(xū)可以遵循莱比锡标注法

当我们学会了标注的方法以后,在写论文的过程中,其实还是会感到麻烦。比如说,你需要思考每个词的意思,而且遇到功能词、语法词的时候,你还需要使用\textsc{}来把字变成小大写。这简直是在考验你手指的灵活度!而且有时你写累了,得反应一段时间才能想到用什么gloss。所以我就在想,能不能让我们的脑子少为这些无聊的事转一会儿,多为真正的研究的内容转一会儿。

我的思路是,首先运用你的字典,从字典中生成一套新的command,然后我们直接用command和原词在LaTeX中生成gloss。然后我们可以把原句复制一遍,换几个符号,就可以编译出gloss啦!太方便!这个任务可以用一个Python的小程式来解决。但当我写出来,发现其实也并不是那么地方便……太失败!不过既然花功夫做了出来,我也就在这里分享一下好了。

首先你要有一个标注好的字典,最好是.txt格式的。如果你用toolbox(坚决反对宗教行为介入科学研究!),你可以直接使用里边的dictionary.txt。比如我弄了以下的绰斯甲语小词典做例子,取名为dic.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
\lx sú
\ps n
\ge cattle

\lx ɟi
\ps suffix
\ge pl

\lx rnɑbɑ̂
\ps n
\ge grass

\lx dzî
\ps vt
\ge eat

其中,\lx代表lexeme,就是词,\ps是part of speech,也就是词类,\ge是gloss in English,英文注释。这些是toolbox词典的基本条目。当然,你也可以选择你喜欢的标注方法。

接下来,我们要做一件事。我们的目标是,把原词做成command,再让这个command指向gloss。比如说,理想情况下,我们输入\sú,编译出来的,就是cattle。但是问题马上就来了。我们的command只能使用ASCII的字母,国际音标的特殊字母是不允许出现的。所以,我们需要一套规则把特殊字母转化成可用的字母。比如,ɟ,我们可以用gy代替,声调我们也可以用f代表降调,h代表高调(绰斯甲语的两个声调)。我们可以根据自己研究语言的不同,制定一套这样的转换规则。

下面,我们就开始写这个Python程式吧。我们先打开你最喜欢的编辑器,存在与dic.txt同一个文件夹里。命名为gloss.py。因为我们等会儿需要运用到正则表达式,所以我们要告诉电脑,我们要用正则表达式了,那我们就在第一行写:

1
import re

然后,我们就让Python打开我们的dic.txt,并阅读它:

1
2
3
tb = open('dic.txt', 'r')
dic = tb.read()
tb.close()

接下来,我们把dic.txt里的空格都删掉,为了方便接下来的任务。

1
dic = dic.replace(' ','')

这都做好了以后,我们要拿出我们刚刚制定好的转换规则(相信你已牢记于心),把这个规则翻译成Python的语言,存在一个新的Python的dictionary里。如以下指令码所示,我把所有不符合规定的字母都换成了合法的字母组合。

1
2
3
4
5
6
dic = dic.replace(' ','')
ascii ={  "ú": "uh",
        "ɟ": "gy",
        "ɑ̂": "aaf",
        "ɑ": "aa",
        "î": "if"}

然后,我们来进行转换:

1
2
for k, v in ascii.items():
    dic = dic.replace(k, v)

接下来,因为我们每个词条有三行,\lx\ps\ge,我们决定最好把它合成一行,只好做如下的动作:

1
2
3
4
5
word = range(0,len(dic),3)
dic = dic.split("\n")
for num, line in enumerate(dic):
    if num in word:
        dic == "".join(dic[num:num+3])

现在呢,我们需要用一条正则表达式,把原词和注释抠出来。因为经过我们以上的处理,原词是被\lx'包围着的,那我们就很容易用正则表达式把它找出来。

1
2
3
dic = str(dic)
entries = re.findall(r'\\lx(.+?)\'' , dic)
glosses = re.findall(r'\\ge(.+?)\'' , dic)

entries就是所有的词,而glosses就是所有的注释。下面,我们需要把这词和注释放在一个\newcommand里边,即如此:\newcommand{\词}{\注释},然后存在一个新的.tex文件里,取名为gloss.tex。因为词典里有的是实词,有的是虚词,而虚词我们是需要用小大写来注释的,所以我们需要用一个if语句,说明如果碰到虚词(比如注释为pl),我们就加一个\textsc{}

1
2
3
4
5
6
7
8
9
tex = open('gloss.tex', 'w')
i = 0
for j in entries:
    if glosses[i] == 'pl':
        tex.write('\\newcommand{\'+entries[i]+'}{\\textsc{'+glosses[i]+'}}\n')
    else:
        tex.write('
\\newcommand{\'+entries[i]+'}{'+glosses[i]+'}\n')
    i = i+1
tex.close()

我们的程式就写好了!现在打开terminal,转换位置到你的文件夹:cd .../.../你的文件夹,输入(我使用的是Python 3):

1
python3 gloss.py

你会发现自动生成了一个gloss.tex文件,打开一看,里边是这样的:

1
2
3
4
\newcommand{\suh}{cattle}
\newcommand{\gyi}{\textsc{pl}}
\newcommand{\rnaabaaf}{grass}
\newcommand{\dzif}{eat
}

成功了!

现在,我们把这个.tex文件input到你的论文里:

1
\input{.../.../gloss.tex}

然后我们试着用新定义的command来标注一个句子:

1
2
3
4
5
6
7
\begin{exe}
\ex
\gll
\ipa{sú=ɟi} \ipa{rnɑbɑ̂} \ipa{dzî}\\
\suh{}=\gyi{} \rnaabaaf{} \dzif{}
\glt Cattle eat grass.
\end{exe
}

出来的就是排列整齐的例子哦。要注意,我们必须在command后边加大括号{},不然编译出来的东西就没有空格。

总结一下,其实这个方法有它的方便之处,但如果你任何词都用新定义的command来注释,那也许会适得其反。不过,如果能把传统标注方法与这个方法结合,可能会更快。尤其是在遇到虚词的时候,用这个方法效率应该会更高,同样,当你一时想不起要标注的词是什么意思的时候,也可以马上使用新的方法,这样就可以节省时间了。当然,最关键的是结合自己目标语言的特点,找到适合自己的方法,修改Python程式,让写论文的效率达到最高。

我把Python文件和小词典放在这个链接里供诸位把玩。

Author: Lai, Yunfan

目前是马克斯普朗克协会人类历史科学研究所(Max-Planck Institut für Menschheitsgeschichte)的博士后。

评论