我有一个分成许多行的文本,没有特定的格式。所以我决定每行line.strip('\n')
。然后我想使用句子结束标记.
将文本拆分成句子:
.
后跟\s
(空格),\S
(如"
'
),后跟[A-Z]
将分裂[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))
PLS!我想知道哪种是掌握正则表达式的最佳方法。这似乎令人困惑。
答案 0 :(得分:4)
要在字符类中包含单引号,请使用 \ 对其进行转义。正则表达式应该是:
\.\s+[A-Z"\']
这就是你真正需要的一切。您只需要告诉正则表达式匹配什么,您不需要指定您不想匹配的内容。一切不符合模式的东西都不匹配。
此正则表达式将匹配任何句点,后跟空格后跟大写字母或引号。由于紧接着一个数字后面紧跟一个字母的句号不符合这些标准,因此不符合。
这假设正如你所说的那样,你所拥有的正则表达式正在努力分割一个句点,然后是空格,后面是一个大写字母。但请注意,这意味着I am Sam. Sam I am.
会分为I am Sam
和am I am
。这真的是你想要的吗?如果不是,请使用零宽度断言来排除要匹配的部分,但也要保留。以下是您的选择,按照我认为您最想要的顺序。
1)保留下一句的句号和第一个字母或开头语;失去空白:
(?<=\.)\s+(?=[A-Z"\'])
这会将上面的示例拆分为I am Sam.
和Sam I am.
2)保留下一句的第一个字母;失去了时间和空白:
\.\s+(?=[A-Z"\'])
这将分为I am Sam
和Sam 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