句段分割是要把成段的原文以句为单位进行分割。

一个基本的想法就是以句号、感叹号和问号等句子结尾用的标点为依据进行分割。

可以写出这样的一个正则操作:Regex.Split(".|!|?",text)。然后,你可以得到一个句子的列表了:

[sentence1,sentence2,sentence3]

但是采用分割的方式会删去这些句号和叹号,更合适的方式是进行替换。

我们常常会见到这样的内容:

---------华丽的分割线-----------

这可以用来作为分割符。然后我们的正则操作是这样的:Regex.replace(".|!|?",text,"$0"&CRLF&"-------------"&CRLF)

得到的结果类似这样:

sentence1.
-------------
sentence2!
-------------
sentence3?

然后,要使用时,就可以再根据分割符把分好的句子导入。

接下来,我们要考虑特殊的情况了。比如英文中的缩写”Mr.”,”Prof.”,还有很多句尾的省略号”……”,会影响分割的正确性。

错误分割的结果类似这样:

Mr.
-------------
Tang is a prestigious professor.
-------------
See you soon!
-------------
!
-------------
!
-------------

首先,我们可以添加一个例外列表,保存Mr.等信息。

Mr.
Mrs.
Ms.
Dr.
Prof.

在句段分割结束后,再删去Mr.这样例外情况后面的分割符。

结果就变成这样了:

Mr. Tang is a prestigious professor.
-------------
See you soon!
-------------
!
-------------
!
-------------

然后针对重复的叹号导致的多次分句的问题,可以修改正则,匹配1到多个感叹号。表达式如下:Regex.replace("!{1,}",text,"$0"&CRLF&"-------------"&CRLF)

Mr. Tang is a prestigious professor.
-------------
See you soon!!!
-------------

另外还有一个问题就是引号。引号通常位于句号的后面,这样进行分句时结果会是这样:

"I love you!
-------------
", he said.

解决办法是先分割.”,!”,?”这样的内容,然后才轮到.!?,而且.!?前面不能是引号。

最终的正则表达式规则是这样的,程序按行读取表达式对原文进行分割。

[\.\?\!]"\s
\.{1,}(?!")
\?{1,}(?!")
\!{1,}(?!")

当然,还会有很多复杂的情况,需要修改规则。

相关源文件:

https://github.com/xulihang/BasicCAT/blob/master/BasicCAT/segmentation.bas

https://github.com/xulihang/BasicCAT/blob/master/BasicCAT/Files/segmentation_en.conf

更新:这样的方法还是显得比较粗糙,句段分割还是应该使用srx格式文件存储规则,并用它提供的算法。使用SRX进行分割的方法见此