2

正则表达式问题在这里!

这是我可以得到的两种线:

a b c d COMMENT
a b c d vs e

我只想解析第一行

这是我要做的:

^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+((v(?!s)|[^v]).+)$

这将干净地解析任何此类行,而不是vs e..... 完成,除非我有多个空格,如下所示:

a b c d  vs e

我正在尝试找到一种方法来指定\s+前面的否定前瞻应该意味着“占用所有可能的空间”而不是它当前所做的

我将如何在正则表达式中编写它?

谢谢!

4

2 回答 2

3

实际上,\s+前面的负面展望确实意味着“占据所有可能的空间”。问题出在其他地方。

vs当正则表达式引擎在使用 读取它们之前解析到最后两个空格时\s+,正则表达式会尝试匹配((v(?!s)|[^v]).+)

它尝试第一个选择v(?!s)当然失败,所以它需要尝试另一个[^v]).+但也失败了,因为当前字符是 a v

这迫使正则表达式引擎回溯并让最后一个\s匹配一个空格,现在引擎重新尝试匹配空格,然后是vs,首先它尝试v(?!s)但失败,因为当前字符是一个空格,然后它[^v]).+再次尝试,现在它成功了因为[^v]匹配一个空格然后.+处理该行的其余部分。

要解决此问题,您可以使用 @pswg 解决方案,或者您可以防止正则表达式回溯 last 读取的空格\s+

如果您使用的是 Java,那么您可以这样做:

^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s++((v(?!s)|[^v]).+)$
                                   ^^
                   Note the double ++, this makes + possessive and prevents backtracking

或者在大多数其他正则表达式风格中,即使在 Java 中,您也可以这样做:

^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)(?>\s+)((v(?!s)|[^v]).+)$
                                 ^^^
                 Notice the atomic group, this prevents backtracking
于 2013-09-05T22:35:01.233 回答
1

问题是第二个空格与[^v]组内的模式匹配。为了防止这种情况,我推荐这种模式:

^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+((v(?!s)|(?!v)\S).+)$

这将确保在组的开头没有捕获任何空格(它必须以\S字符开头)。

于 2013-09-05T22:00:07.297 回答