我的做法很简单:采用一种人机合作的方式,用程序做计算机最容易做的事情(因为我会写程序),自己做计算机难以做好的事情(实际上,也就是那些我认为写程序来做比较困难,不如自己手工做更简单方便的事情)。计划去做一个“全自动”的中文索引生成系统恐怕是事倍功半,从下面讨论可以看到其中的困难。
下面以做翻译书的索引为例,我的工作过程大致分为几个阶段:
1.计划好一种生成索引的工作程序(并非计算机程序,而是人做这件事情的计划);
2.准备好基础材料,包括原索引的逐条译文及原索引页码(这是总要做的);
3.编几个小程序(关键是考虑清楚需要用程序完成什么工作);
4.在检查排印好的校对稿时填入中文书页码(首先需要计划一种方便方式),排序生成索引(计算机做这些事情很容易,但怎么做呢?);
5.检查所生成的索引,处理其中的遗留错误和问题(这部分工作只有自己认真做,只要初期计划良好,遗留问题是很少的)。
最重要的是第1步,需要有一个计划。在做《程序设计实践》一书的索引时,我编程序用了半个上午,其间还调整调整基础材料(第一次用这种方式做翻译书的索引,初期计划不周),填中文页码用了几个小时,检查调整用了一两小时。共用了大约一天时间,应该算是一件很简单的事情了。
下面用一个例子介绍一种具体方法。注意,这里介绍的不过是完成此事的一种可能方式。读者可以举一反三,找出无数种不同的索引生成方式。因此,请不要过于看重下面的具体做法。我一点也不看重它,下次再做时可能就会另想一种更合理适用的方式。有关计划无须专门讨论,它蕴涵在下面的一系列步骤之中。
步骤一,准备材料
首先基于原书索引准备一份翻译好的基本材料。在做此事时我用普通文本文件,因为文本文件容易用程序处理。例如,下面可能是材料中的几行:
……
在线(online)38,175
和连接(and linkage)39
函数(function)38,175
成员函数(member function)175
输入(input)27,217
……
我在每个第二级索引之前留一个空格(也可以用tab符号),用这个字符区分第一级和第二级索引。在括起英文原词的括号前也有意留一个空格,下面将看到这个空格的用处。基础材料必须尽可能保持内在一致性,以使自己需要写的程序比较简单。
步骤二,填充、展开、排序
需要编写的第一个小程序是前加工程序,它完成几项工作:首先在每个二级索引前填充有关的一级索引词,并在一级索引词之后加一个逗号作为分隔符。用这些替代原有的空格。填充后,上述几个具体索引行将变成:
在线(online)38,175
在线,和连接(and linkage)39
在线,函数(function)38,175
在线,成员函数(member function)175
输入(input)27,217
程序工作的下一步是将它们展开为每个页码一行的形式。上述几行展开之后得到:
在线(online)38
在线(online)175
在线,和连接(and linkage)39
在线,函数(function)38
在线,函数(function)175
在线,成员函数(member function)38
输入(input)27
输入(input)217
程序最后一步是按索引项的英文页码(看作数值)对它们做一次排序,并将排序结果输出到一个文本文件里。这样就做好了填写中文页码之前的准备工作。对索引项按英文原书的页码排序,这将使填充新页码的工作变得简便快捷。
步骤三,填入中文页码
拿到书籍排印出的校对稿后,就可以用一个正文编辑器填写中文页码了。由于在准备好的文件中索引项是按照英文从第一页到最后一页排序的。因此,填写页码的整个工作中只需要将校对稿从头至尾翻一遍,根本不必参考原书(除非原页码有错)。这样,填页码就是一种简单劳动,虽然枯燥无味,但很快就能做完。一本书绝少有超过10000个索引项的,填好它并不需要太多时间。例如,《程序设计实践》的索引展开后有3000项左右,我只用几个小时就填完了。在此过程中。我们还可以顺便检查术语的合理性和一致性等。由于是在计算机上操作,其间可通过查找功能解决修改的一致性问题。
步骤四,排序归并输出
随后的工作就是用一个后处理程序完成索引的排序和输出。中文排序似乎很困难,还好,直接按照GB的编码排序就能解决绝大部分问题(假定这里想生成是按照汉语拼音排序的索引)。在计算机书籍的索引项中生僻字很少,其中出现大部分汉字都属于一级汉字,其编码就是按拼音顺序排列的。我原来做的时候,就是直接将汉字存入普通字符串,用简单的字符串比较作为排序准则。
由于一级索引词后的空格小于二级索引中的逗号(这也是预先计划好的),在排序结果中一级索引和与之相关的二级索引的相对位置自然正确。在前加工阶段填入一级索引词,就是为了保留有关索引项之间的联系,保证能自动得到正确的排序结果。
排序后还需做两件事情:一是需要合并相同的索引项(它们都处于相邻位置,程序里很容易确定),并收集有关的页码。如果采用稳定的排序算法,排序之后,相同索引项还是按页码顺序排列的。即使手头没有稳定的排序算法,自己解决各个索引项中几个页码的排序也很容易。此外,在将排序整理好的索引表输出到文件的过程中,应删除二级索引之前原先加入的一级索引词,并加上适当空格。至此,有关工作就基本完成了。
步骤五,人工检查纠错
无论我们怎样策划,编写出多么高级的程序,生成的索引里一定还会有问题,因此必须经过人工的检查和调整,纠正其中的差错。例如:
1.索引项中可能出现二级汉字,其排序位置不正确。如果这种字不是索引项的第一个字,问题将是局部性的。远距离调整的情况也可能出现。可能的改进方式是另定义中文字符序(按照拼音)的映射表。解决这一问题并不困难。但对于我个人的工作而言,完全没有必要去花时间去做一套。
2.多音字的问题无法解决(例如“行”,“重”之类)。这个问题必须由懂专业的人自己查看和调整。这一问题的自动解决将非常困难,还是将它留给专门研究中文信息处理的人们。在书籍索引中这种问题很罕见,自己调整一下就可以了。
3.我们可能还需手工将索引按照拼音分段等等。
显而易见,由于初始的计划和相应考虑,在最后一步遇到的问题或者很罕见,或者很局部,或者很简单,处理起来并不费时间。
至此一切工作都完成了。当然,这一做法绝非完美。可想到的一个重要缺陷就是正文文本中没有字体信息,而许多计算机书籍的索引中有字体问题(虽然目前许多出版社在字体方面很不负责)。在做《程序设计实践》的索引时,我在交译稿时生成了一份不包括页码的按中文排序的索引,其中整理好字体,送给出版社去排版。校对时生成带中文页码的索引,请出版社填入。看来,如何做索引的问题还值得进一步研究。但无论如何,基于上面的基本做法,得出“做索引不难”的结论应该是没有疑义了。
当然,上面介绍中还省略了许多细节。例如:英文词索引项的大小写排列问题;有些标点符号索引项也可能需要特殊处理。这些都不是本质性困难,只是一些需要处理的细节。有些极特殊的问题甚至可以不在程序里处理,留到最后检查整理时人工解决。
如果需要按其他方式排序,问题也可以解决。只需特别去定义一种字符序判断操作,在后处理阶段按这种比较准则对索引项排序就可以了。
可能有同行会问,“中文书的索引该怎么做呢?”这个我也做过,同样简单:计划一种工作方式,编几个小程序。这里不必多说了,算是本文留下的一道小小程序应用题。
后记:写完这篇小文,还想说几句话。我在这里做的不过是编几个小小的文本处理程序,让它们修改字符串,对字符串以不同方式排序。这些都是写程序的人最熟悉的东西,但为什么许多人没有这样做呢?教训是:作为掌握了程序技术的人,更重要可能是看到在哪里需要写程序。一味蛮干只能是费力不讨好。
另一方面,我写本文也是觉得这类技术值得传播,以改进数字化后的出版工作。我还希望此文能促使人们做好更多的中文计算机书籍的索引,以利于广大读者。也想借本文告诉作者们和出版社:索引的问题并不难解决,“请做好你的索引!”这是出版社(或者作者)的责任,而且是可以轻易完成的工作。
这里的技术同样适用于非计算机书籍。当然,如果作者不熟悉计算机,要他们去编写程序就是勉为其难了。因此,出版社应该计划一种方式,让作者负责其中某些阶段的工作。这样,做好索引也是没有问题的,大家同样可以很轻松。
(本文作者为北京大学数学学院信息科学系教授)