【问题标题】:Sentence matching with regex与正则表达式匹配的句子
【发布时间】:2013-08-05 13:46:21
【问题描述】:

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

  1. 句点. 后跟\s(空格)、\S(如"')和[A-Z] 将拆分
  2. 不要拆分[0-9]\.[A-Za-z],比如1.stackoverflow real time solution

我的程序只解决了 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))

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

【问题讨论】:

标签: python regex python-2.7 text-segmentation


【解决方案1】:

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

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

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

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

正如您所说,这是假设您使用的正则表达式正在拆分句点,然后是空格,然后是大写字母。但是请注意,这意味着I am Sam. Sam I am. 将拆分为I am Samam I am。这真的是你想要的吗?如果没有,请使用零宽度断言来排除要匹配但也要保留的部分。以下是您的选项,按照我认为您最可能想要的顺序排列。

1) 保留句号和下一句的第一个字母或开头引号;丢失空格:

(?&lt;=\.)\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 的数组+ b @ 987654340@ c 而不仅仅是 a b c)。

3) 保留一切;空格与前一句搭配:

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

这会给你I am Sam.Sam I am.

关于你问题的最后一部分,我见过的正则表达式语法的最佳资源是http://www.regular-expressions.info。从这个摘要开始:http://www.regular-expressions.info/reference.html 然后转到教程页面了解更多高级细节:http://www.regular-expressions.info/tutorial.html

【讨论】:

  • 如果你使用这个表达式来分割字符串,那么你会不会丢失句点,更重要的是分割过程中下一行的第一个字符?使用\.\s+(?=[A-Z"\']) 之类的前瞻可能会更好。
  • 我想是这样 - 这对我来说似乎更有用并且似乎是暗示的,但他说他的正则表达式 正在按他预期的“1的一半”工作"(即整个事情,因为#2是他不想匹配的特定情况,不需要指定)。唯一缺少的是转义的单引号。我想如果这不是他想要的,他可以回来这么说,但这与他所说的解决分裂的说法是矛盾的,然后是空格,然后是大写字母。但我会编辑答案以包括所有选项以确保完整性。
  • 嗨,正则表达式 '\.\s+([AZ“\'])' 进行句子拆分,但我注意到以下错误,例如拆分 [0-9].[AZ] 而不是分裂'。在 "" 之后是 [A-Z]。就像在这种情况下:“在他父亲的指导下,他是地球的创造者。“万物都是由他创造的;没有任何东西是由他创造的”(约翰福音 1:3)。对于任何延误,我深表歉意。谢谢@All。我尝试了前瞻表达式并得到:sre_constants.error: invalid group reference。
  • 不清楚你的例子是什么意思,因为你没有具体说明会发生什么。您可以在问题中添加示例并指定您获得的结果集吗?该正则表达式绝对不应该拆分数字周期大写,因为在句点之后至少有一个空格字符需要。另外,请注意我给出的关于在拆分中使用捕获组的警告。为什么要将角色类放在捕获组中?它应该在前瞻断言中。试试我的 #2 正则表达式。
  • 哦,我刚刚注意到您匹配的是左引号,而不是直引号。尝试将开头的双引号更改为\u201d,将单引号更改为\u2018(只有一个斜线)。但肯定也将捕获组更改为前瞻断言。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 2011-02-08
  • 1970-01-01
  • 2011-07-30
  • 1970-01-01
相关资源
最近更新 更多