组合多个正则表达式1用于匹配和休息以进行排除

时间:2014-02-09 19:22:00

标签: python regex

我想创建一个可以将文本拆分成句子的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,它不是。

正确的输出应该是一个句子列表

错误的输出是任何拆分。不标记句子的结尾

2 个答案:

答案 0 :(得分:2)

您可以考虑仅在模式6上进行拆分,然后使用外观来排除模式3和5,因为尽管执行模式6(模式3在句点之后具有空格+大写,模式5用于必须),但这些模式仍然可以匹配忽略连续的句号。)

这是模式6,具有正向前瞻:

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

要排除模式3,请添加负面的lookbehinds:

(?<!Mr|Dr|Jr)(?<!Mrs)\.(?=\s[A-Z])

我使用了一个单独的负面lookbehind因为python的lookbehinds不能是可变宽度。 MrDrJr的所有内容均为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()