我想创建一个可以将文本拆分成句子的python函数。我想拆分句点(。),问号(?)或感叹号(!)。但是,我已经确定了这个标准的一些排除,我已经确定为正则表达式。 pattern1到5用于排除,pattern6用于匹配。我想找到所有匹配pattern6的模式但不能匹配任何模式1到5.是否可以在Python正则表达式中这样做?或者我没有想出正确的方向。
pattern1 = '\. [a-z]'
pattern2 = '\.\d'
pattern2 = '(Mr|Mrs|Dr|Jr)\. [A-Z]'
pattern4 = '[a-zA-Z]\.[a-zA-Z]'
pattern5 = '\.(\.|,)'
pattern6 = '\.[\s][A-Z]'
当我将模式1到5与|组合时在pythex中,
pattern1|pattern2|patter3|pattern4|pattern5
我可以找到我想要排除的所有场景。然后我尝试用^排除它们并与pattern6结合得到一个非常难看的正则表达式:
(^((\. [a-z])|(\.\d)|((Mr|Dr|Jr|Mrs)\.[A-Z])|([A-Za-z]\.[A-Za-z])|(\.(\.|,))))|(\.[\s][A-Z])
为简单起见,这里的模式替换为模式名称
(^((pattern1)|(pattern2)|(pattern3)|(pattern4)|(pattern5)))|(pattern6)
这在某种程度上是有效的,但是对于" Mr。史密斯"我刚刚开始学习正则表达式,所以请原谅我的脏代码。如果您能为编写良好的可读正则表达式提供指导,将不胜感激。
添加样本输入:
先生。史密斯以150万美元的价格买下了cheapsite.com,即他付了一笔钱 很多。他介意吗? Adam Jones Jr.认为他没有。在任何情况下, 这不是真的......嗯,概率为.9,它不是。
正确的输出应该是一个句子列表
错误的输出是任何拆分。不标记句子的结尾
答案 0 :(得分:2)
您可以考虑仅在模式6上进行拆分,然后使用外观来排除模式3和5,因为尽管执行模式6(模式3在句点之后具有空格+大写,模式5用于必须),但这些模式仍然可以匹配忽略连续的句号。)
这是模式6,具有正向前瞻:
\.(?=\s[A-Z])
要排除模式3,请添加负面的lookbehinds:
(?<!Mr|Dr|Jr)(?<!Mrs)\.(?=\s[A-Z])
我使用了一个单独的负面lookbehind因为python的lookbehinds不能是可变宽度。 Mr
,Dr
和Jr
的所有内容均为2个字符,但Mrs
3。
您可以将最后一个正则表达式缩短为:
(?<![MDJ]r)(?<!Mrs)\.(?=\s[A-Z])
现在排除模式5,另一个负面的背后隐藏:
(?<![MDJ]r)(?<!Mrs)(?<!\.)\.(?=\s[A-Z])
此后,它不会连续分割。
现在你已经有一段时间了,你可以轻松地使用一个字符类来分割!
和?
:
(?<![MDJ]r)(?<!Mrs)(?<!\.)[.?!](?=\s[A-Z])
顺便说一下,^
并不完全用于正则表达式中的否定。相反,当您不关心字符的顺序时,[^ ... ]
用于否定。例如,[^aeiou]
将按任意顺序匹配除aeiou
字母之外的任何一个字符。此外,正则表达式中的大多数元字符在字符类中失去意义(这是方括号中的内容)。例如,()
成为[]
之间的字面字符,不能再用于分组。
^
在字符类之外用于表示行的开头。
答案 1 :(得分:0)
据我所知,没有排除模式^
用于排除字符集中的字符,如[^ ab]外面的意思是字符串的开头不是你想要的
你必须做两步比赛
pattern1 = r'\. [a-z]'
pattern2 = r'\.\d'
pattern2 = r'(Mr|Mrs|Dr|Jr)\. [A-Z]'
pattern4 = r'[a-zA-Z]\.[a-zA-Z]'
pattern5 = r'\.(\.|,)'
pattern6 = r'\.[\s][A-Z]'
if re.match(pattern6):
if not re.match("("+pattern1+"|"+pattern2+"|"+pattern3+"|"+pattern4+"|"+pattern5+")"):
do_whatever_you_want()