为什么这个正则表达式不起作用?也许是因为两个长相落后



我有这个正则表达式:(?<![A-Z])(?<=[.!?])s(?=[A-Z])它把一个段落分成几个句子(基于每个空格(。

我在这一段中使用了它:Did he know that J. Smith is a name? The term is most commonly applied to the placing of a warship in active duty with its country's military forces. The ceremonies involved are Often rooted in centuries old naval tradition. I.D. is a wonderful word.

它打断了"J.Smith",因为它认为"."代表一个句子的结尾。

我使用re.split((并打印出数组,用换行符分隔值

这是上面一段的输出:

Did he know that J.
Smith is a name?
The term is most commonly applied to the placing of a warship in active duty with its
country's military forces. (no newline at beginning of sentence)
The ceremonies involved are Often rooted in centuries old naval tradition.
I.D. is a wonderful word.`

它适用于"身份证",但为什么不适用于"J·史密斯"呢?从逻辑上讲,它应该。。。

我想让它检测字符串中的这个结构:

没有大写字母+句点/?/+空白+大写字母

后向(或前向(是一个零宽度断言—也就是说,它在断言为true的任何点匹配一个零长度的字符串。

特别是,这意味着,如果您的regexp中有两个连续的lookbehind(或lookahead(断言,那么只有当它们在同一点上都匹配时,它们才会匹配

因此,如果前一个字符不是范围A-Z中的大写字母,则(?<![A-Z])(?<=[.!?])匹配,如果它是字符.!?之一,则匹配。显然,后一个断言暗示了前一个断言,所以正则表达式的(?<![A-Z])部分没有实际效果。

看起来想要断言的是前一个字符是.!?,而前一个不是大写字母。如果是这样,一种解决方案是用(?<![A-Z].)替换(?<![A-Z])


Ps。原始正则表达式没有拆分为"I.D. is"的原因是,第一个句点后面没有用于匹配s的空格,并且第二个句点后面的空格后面没有按照前瞻性断言的要求紧跟大写字母。

除了@unsubu的观点之外,它可能没有达到你预期的效果,因为你在同一个字符上断言两个lookbehinds,你在说,"前一个字符不是[A-Z],它[.!?]。">

(?<=(?<![A-Z])[.!?])s(?=[A-Z])

最新更新