我希望找到一个正则表达式,它可以将段落(长字符串,无需担心的换行符)分解为句子,其中一个简单的规则是{。,?,!}后面跟一个空格然后一个大写字母应该是句子的结尾(我意识到这对现实生活来说不是一个好的规则)。
我有部分工作,但它并没有完成这项工作:
line = 'a b c FFF! D a b a a FFF. gegtat FFF. A'
matchObj = re.split(r'(.*?\sFFF[\.|\?|\!])\s[A-Z]', line)
print (matchObj)
打印
['', 'a b c FFF!', '', ' a b a a FFF. gegtat FFF.', '']
而我想得到:
['a b c FFF!', 'D a b a a FFF. gegtat FFF.']
所以有两个问题。
为什么结果中有空成员(''
)?
我理解为什么D
会从分割结果中删除 - 这是第一次搜索的一部分。如何以不同的方式构建我的搜索,以便在标点符号后面的大写字母被放回,以便它可以包含在下一句中?在这种情况下,如何在分割结果的第二个元素中显示D?
我知道我可以通过某种for-loop实现这一目的,只是剥离第一个结果,加回大写字母,然后重新做一遍,但这似乎不是那么Pythonic。如果正则表达式不是这里的方法,还有什么东西仍然可以避免for循环吗?
感谢您的任何建议。
答案 0 :(得分:5)
要解决第一个问题(split()
返回的结果中的空字符串),使用findall()
或finditer()
< /强>:
>>> re.findall(r'(.*?\sFFF[\.|\?|\!])\s[A-Z]', line)
['a b c FFF!', ' a b a a FFF. gegtat FFF.']
您在输出中看到空字符串,因为split()
应该做什么:使用匹配的组作为分隔符拆分输入字符串。
对于第二个问题(输出中缺少 D ),使用lookahead assertion (?=...)
强>:
>>> re.findall(r'(.*?\sFFF[\.|\?|\!])\s(?=[A-Z])', line)
['a b c FFF!', 'D a b a a FFF. gegtat FFF.']
前瞻,否定前瞻,外观和负面观察是四种断言,你可以用来说'#34;只有在跟随/先于群组时匹配这个群组,但不要使用字符串&#34;
仔细阅读您的表达,似乎您误解了[...]
运算符的语法。您似乎想要匹配.
,?
和!
中的一个。
如果是这种情况,那么您可以将[\.|\?|\!]
重写为[.?!]
:
>>> re.findall(r'(.*?\sFFF[.?!])\s(?=[A-Z])', line)
['a b c FFF!', 'D a b a a FFF. gegtat FFF.']
[.?!]
不仅更紧凑,而且更正确:[\.|\?|\!]
您还匹配|
字符(因此'a b c FFF|'
是有效匹配) !