句子与正则表达式匹配

时间:2013-08-04 22:26:28

标签: python regex python-2.7 text-segmentation

我有一个分成许多行的文本,没有特定的格式。所以我决定每行line.strip('\n')。然后我想使用句子结束标记.将文本拆分成句子:

  1. 句点.后跟\s(空格),\S(如" '),后跟[A-Z]将分裂
  2. 不要像[0-9]\.[A-Za-z]那样拆分1.stackoverflow real time solution
  3. 我的程序只能解决1 - 周期(。)的一半,然后是\ s和[A-Z]。以下是代码:

    # -*- coding: utf-8 -*-
    import re, sys
    
    source = open(sys.argv[1], 'rb')
    dest = open(sys.argv[2], 'wb')
    sent = []
    for line in source:
        line1 = line.strip('\n')
        k = re.sub(r'\.\s+([A-Z“])'.decode('utf8'), '.\n\g<1>', line1)
        sent.append(k)
    
    for line in sent:
        dest.write(''.join(line))
    

    PLS!我想知道哪种是掌握正则表达式的最佳方法。这似乎令人困惑。

1 个答案:

答案 0 :(得分:4)

要在字符类中包含单引号,请使用 \ 对其进行转义。正则表达式应该是:

\.\s+[A-Z"\']

这就是你真正需要的一切。您只需要告诉正则表达式匹配什么,您不需要指定您不想匹配的内容。一切不符合模式的东西都不匹配。

此正则表达式将匹配任何句点,后跟空格后跟大写字母或引号。由于紧接着一个数字后面紧跟一个字母的句号不符合这些标准,因此不符合。

这假设正如你所说的那样,你所拥有的正则表达式正在努力分割一个句点,然后是空格,后面是一个大写字母。但请注意,这意味着I am Sam. Sam I am.会分为I am Samam I am。这真的是你想要的吗?如果不是,请使用零宽度断言来排除要匹配的部分,但也要保留。以下是您的选择,按照我认为您最想要的顺序。

1)保留下一句的句号和第一个字母或开头语;失去空白:

(?<=\.)\s+(?=[A-Z"\'])

这会将上面的示例拆分为I am Sam.Sam I am.

2)保留下一句的第一个字母;失去了时间和空白:

\.\s+(?=[A-Z"\'])

这将分为I am SamSam I am。这假定之后有更多的句子,否则句号将与第二句一致,因为它后面没有空格和大写字母或引号。如果这个选项是您想要的 - 句子没有句点,那么您可能还希望匹配一个句点后跟字符串结尾,以及可选的插入空格,以便最后一个句点和任何尾随空格都将被删除:

\.(?:\s+(?=[A-Z"\'])|\s*$)

请注意?:。您需要非捕获括号,因为如果拆分中有捕获组,则组中捕获的任何内容都将作为元素添加到结果中(例如split('(+)', 'a+b+c'会为您提供a {{1 }} + b +而不只是c a b)。

3)保持一切;空格与前一句一致:

c

这会为您(?<=\.\s+)(?=[A-Z"\']) I am Sam.

关于问题的最后一部分,我见过的最好的正则表达式语法资源是http://www.regular-expressions.info。从此摘要开始:http://www.regular-expressions.info/reference.html然后转到“教程”页面以获取更多高级详细信息:http://www.regular-expressions.info/tutorial.html