我正在尝试一些对我来说应该很显然但却不是的事情。 我想匹配一个不包含特定字符序列的字符串。 我已经尝试使用 [^ab]
, [^(ab)]
等来匹配不包含'a'或'b'的字符串,或只包含 'a' 或只包含 'b' 或者 'ba' 但不匹配 'ab'。 我给出的这些示例确实不会匹配 'ab',但也不会单独匹配 'a',而我需要它们这样做。 有没有简单的方法可以做到这一点?
我正在尝试一些对我来说应该很显然但却不是的事情。 我想匹配一个不包含特定字符序列的字符串。 我已经尝试使用 [^ab]
, [^(ab)]
等来匹配不包含'a'或'b'的字符串,或只包含 'a' 或只包含 'b' 或者 'ba' 但不匹配 'ab'。 我给出的这些示例确实不会匹配 'ab',但也不会单独匹配 'a',而我需要它们这样做。 有没有简单的方法可以做到这一点?
使用字符类(如[^ab]
)可以匹配不在字符集中的单个字符。(其中^
是否定部分)。
要匹配不包含多字符序列ab
的字符串,您需要使用负向先行断言:
^(?:(?!ab).)+$
以上表达式在正则表达式注释模式下的解析是:
(?x) # enable regex comment mode
^ # match start of line/string
(?: # begin non-capturing group
(?! # begin negative lookahead
ab # literal text sequence ab
) # end negative lookahead
. # any single character
) # end non-capturing group
+ # repeat previous match one or more times
$ # match end of line/string
^((?!ab).+)$
。 - phil294(.|\n)
。 - Thiago Mata^(?!.*ab).*$
更新:在下面的评论中,我已经说明这种方法比Peter's answer提供的方法慢。自那时以来,我进行了一些测试,发现它确实稍微快一点。然而,选择这种技术而不是其他技术的原因不是速度,而是简单性。
另一种技术,在这里描述为温和贪婪的标记,适用于更复杂的问题,比如匹配由多个字符组成的分隔文本(如HTML,正如Luke在下面评论中所说)。对于问题的描述,这太过复杂。
对于任何感兴趣的人,我使用了一大段Lorem Ipsum文本进行测试,计算不包含单词“quo”的行数。以下是我使用的正则表达式:
(?m)^(?!.*\bquo\b).+$
(?m)^(?:(?!\bquo\b).)+$
windows
的 <td> .. </td>
元素,这些元素在开始和结束标签之间出现,并且不匹配那些不包含的 TD 元素。我使用了 <td(?:(?!</td>).)+</td>
来查找整个 TD 元素,其中 <td(?!.*</td>).*</td>
无法工作。最终的正则表达式是 <td(?:(?!</td>).)+windows.*?</td>
。关于“将知识分解成更小的块”的一个很好的例子,请参见下面的答案,其中包括所使用的正则表达式字符的解释。 - Luke是的,它被称为负向前瞻。它的格式是 - (?! 正则表达式)
。因此,abc(?!def)
将匹配不跟在 def 后面的 abc。所以它将匹配 abce、abc、abck 等。
类似地,有正向前瞻 - (?= 正则表达式)
。因此,abc(?=def)
将匹配 abc 后面紧跟着的 def。
还有负向后顾 - (?<! 正则表达式)
和正向后顾 - (?<= 正则表达式)
需要注意的一点是,负向前瞻是零宽度的。也就是说,它不算占用任何空间。
所以看起来 a(?=b)c
会匹配 "abc",但实际上不会。它将匹配 'a',然后与'b'进行正向前瞻,但不会向前移动字符串。然后它将尝试使用 'b' 将 'c' 与之匹配,这是不起作用的。同样,^a(?=b)b$
将匹配 'ab' 而不是 'abb',因为在大多数正则表达式实现中,前瞻是零宽度的。
更多信息请参考此页面
?!
可以忽略该组,但它仍然匹配字符串的其余部分。是否有一种方法可以使用它来排除整行,如果它具有特定模式? - Guilherme Taffarel Bergaminabc(?!def)将匹配不跟在def后面的abc。所以它将匹配abce、abc、abck等。如果我既不想要def也不想要xyz,那么会是abc(?!(def)(xyz))吗?
我有同样的问题,并找到了解决方案:
abc(?:(?!def))(?:(?!xyz))
abc(?:(?!def)(?!xyz))
就可以了。它们已经在非捕获组中了。不需要再把另一个放进去。它们也不是“由“AND”组合而成的”。它们一个接一个地被检查,就像 ab
首先被检查是否为 a
,然后再检查是否为 b
,但是前瞻不会移动光标。 - Scratte按照您所描述的方式使用正则表达式是简单的方法(就我所知)。如果您想要一个范围,可以使用 [^a-f]。
最简单的方法是完全将否定从正则表达式中提取出来:
if (!userName.matches("^([Ss]ys)?admin$")) { ... }
只需在字符串中搜索“ab”,然后取反结果:
!/ab/.test("bamboo"); // true
!/ab/.test("baobab"); // false
看起来更简单,而且应该更快。
[^ab]
是一个字符类,它匹配除了a和b之外的所有内容。显然,它将匹配空格。 - Scratteif (StringToTest.IndexOf("ab") < 0)
//do stuff
这种方法可能会更快(与上面的正则表达式相比,快速测试显示该方法只需要约25%的时间)。一般来说,如果我知道我要查找的确切字符串,我发现正则表达式过于复杂。由于您知道不想要“ab”,因此可以简单地测试字符串是否包含该字符串,而无需使用正则表达式。