如果我想找到所有位于段落末尾的句点,可以使用\.($|\n)
。但是如何否定它并表示“后面跟着任何不是这些字符之一的字符”,因为元字符无法在字符类中使用,这阻止了我使用否定字符类?
如果我想找到所有位于段落末尾的句点,可以使用\.($|\n)
。但是如何否定它并表示“后面跟着任何不是这些字符之一的字符”,因为元字符无法在字符类中使用,这阻止了我使用否定字符类?
美元符号$
有什么作用?这要看情况!
答案非常取决于您使用的语言和正则表达式引擎。你看,
$
断言我们定位在字符串末尾或者在字符串末尾的任何回车符或换行符之前。因此,您可以使用\.(?!$)
来确保安全。$
断言我们定位在字符串末尾或在字符串末尾的任何换行符之前。因此,您可以使用\.(?!$|\r)
。$
断言我们定位在字符串的末尾。因此,您需要使用完整的正则表达式:\.(?!$|[\r\n])
。因此,对于多引擎方案,最安全的办法是:
\.(?!$|[\r\n])
但是在正确的上下文中,另外两个选项也是完全可以接受的。
说明
\.
匹配字面上的句号(?!$|[\r\n])
断言后面不是“字符串的结尾”、回车符或换行符。\R
成为正则表达式语言的一部分,这并非没有原因。请查看我的回答。 - tchrist (?x: # enable comments
\. # a literal dot character
(?! # look ahead for not the following{
\R ? # optional EOL grapheme cluster
\z # at the true end of string
) # } end look ahead
)
(?=\R)
\R?
改为\R*
可能更合适,以防万一记录末尾有多个行终止符,比如连续几个换行符。这样可以允许0、1、2或者更多的EOL图形符号出现在字符串末尾。\R{2,}
,但整个部分都是可选的,如果这种情���下需要,则返回结果如下: (?x: # enable comments
\. # a literal dot character
(?! # look ahead for NOT the following {
(?:
\R {2,} # two or more EOL grapheme clusters
) ? # # optionally
\z # at the true end of string
) # } end negated look ahead
)
如果您的正则表达式中没有来自UTS 18:Unicode 正则表达式- 行边界的\R
,那么您将不得不用更为烦人的方法把它写出来:
(?x: # We are emulating \R per UTS#18
(?> # Prohibit backtrack within subpattern
\r \n # Match a CRLF without backtracking
# or else any code point with the
# vertical space character property
# \p{VertSpace}, here enumerated in full
| [\x0A-\x0D\x85\x{2028}\x{2029}]
)
)
\R{2}
这样的匹配只能匹配一个CRLF,而不能这样做。\R
,因为我担心我的答案已经有点复杂了(事实上,OP选择了一个在Windows上可以匹配字符串末尾句号的解决方案...)。但是您的讨论绝对是精湛的,就像我偶然发现的其他文章一样。从现在开始,我可能不得不寻找它们。 :) 实际上,仅仅今天早上,我就将您的一个答案添加到了“我喜欢阅读的答案”部分中!+1,很抱歉我不能+5 :) - zx81
\n
处使用类似于\n{2,}
的表达式可能是最好的选择。然而,在某些情况下,单独的换行符本身并不足以表示段落分隔符(例如在Markdown或电子邮件中),甚至在HTML中也可能不够用。 - tchrist