regex 正则表达式和否定整个字符组[重复]

wlsrxk51  于 2023-10-22  发布在  其他
关注(0)|答案(9)|浏览(115)

此问题已在此处有答案

Regular expression to match a line that doesn't contain a word(34答案)
六年前就关门了。
我正在尝试一些我觉得对我来说应该是相当明显的事情,但事实并非如此。我试图匹配一个不包含特定字符序列的字符串。我试过使用[^ab][^(ab)]等。匹配不包含“a”或“B”的字符串,或者只包含“a”或"B“或”ba“但不匹配”ab“的字符串。我给出的例子不会匹配'ab',这是真的,但它们也不会单独匹配'a',我需要它们。有没有简单的方法可以做到这一点?

nwo49xxi

nwo49xxi1#

使用字符类(如[^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
nom7f22z

nom7f22z2#

使用负前瞻(参见Regexr.com explanation):

^(?!.*ab).*$

更新:在下面的评论中,我指出这种方法比Peter's answer中给出的方法慢。从那以后,我做了一些测试,发现它真的稍微快一点。然而,这种技术优于其他技术的原因不是速度,而是简单性。
另一种技术,在这里被描述为 tempered greedy token,适用于更复杂的问题,例如匹配分隔符由多个字符组成的分隔文本(如HTML,如Luke在下面评论的)。对于问题中描述的问题,这是矫枉过正。
对于任何感兴趣的人,我用一大块Lorem Ipsum文本进行了测试,计算了不包含单词“quo”的行数。以下是我使用的正则表达式:

(?m)^(?!.*\bquo\b).+$

(?m)^(?:(?!\bquo\b).)+$

无论我是在整个文本中搜索匹配,还是将其分解为行并单独匹配,锚定的前瞻始终优于浮动的前瞻。

dy1byipe

dy1byipe3#

这就是所谓的消极前瞻。它是这样的-(?!regex here)。所以abc(?!def)将匹配abcnot后跟def。所以它会匹配abc,abc,abc,等等。
类似地,存在正向前看-(?=regex here)。所以abc(?=def)将匹配abc后面跟着def。
还有负向后看和正向后看-分别为(?<!regex here)(?<=regex here)
需要注意的一点是,负前瞻是零宽度的。也就是说,它不算占用了任何空间。
因此,它看起来像a(?=b)c将匹配“abc”,但它不会。它将匹配'a',然后是'B'的正向前看,但它不会向前移动到字符串中。然后,它将尝试将“c”与“B”匹配,但这不起作用。类似地,^a(?=b)b$将匹配'ab'而不是'abb',因为查找范围是零宽度的(在大多数正则表达式实现中)。
有关this页面的更多信息

bbuxkriu

bbuxkriu4#

abc(?!def)将匹配abc而不是def。所以它会匹配abc,abc,abc,等等。如果我既不想要def也不想要xyz,它会是abc吗?!(def)(xyz))???
我也有同样的问题,并找到了解决办法:

abc(?:(?!def))(?:(?!xyz))

这些不计数的组由“AND”组合,所以这应该可以做到这一点。希望有帮助。

vdzxcuhz

vdzxcuhz5#

使用你描述的正则表达式是一种简单的方法(据我所知)。如果你想要一个范围,你可以使用[^a-f]。

ctehm74n

ctehm74n6#

最简单的方法是完全从正则表达式中提取否定:

if (!userName.matches("^([Ss]ys)?admin$")) { ... }
u0njafvf

u0njafvf7#

只需在字符串中搜索“ab”,然后对结果求反:

!/ab/.test("bamboo"); // true
!/ab/.test("baobab"); // false

这似乎更容易,也应该更快。

mw3dktmi

mw3dktmi8#

在这种情况下,我可能只是简单地避免正则表达式,并使用如下内容:

if (StringToTest.IndexOf("ab") < 0)
  //do stuff

这可能也会快得多(上面对regex的快速测试显示,该方法占用的时间约为regex方法的25%)。一般来说,如果我知道要查找的字符串,我会发现正则表达式是多余的。因为你知道你不想要“ab”,所以测试字符串是否包含该字符串是一件简单的事情,而不需要使用正则表达式。

8hhllhi2

8hhllhi29#

例如,正则表达式[^ab]将匹配'ab ab ab',但不匹配'ab',因为它将匹配字符串' a'或'b '。
你有什么语言/场景?你能从原始集合中减去结果,然后只匹配ab吗?
如果您使用GNU grep,并且正在解析输入,请使用'-v'标志来反转结果,返回所有不匹配的结果。其他正则表达式工具也有一个“返回非匹配”函数。
如果我理解正确的话,你想要所有的东西,除了那些在任何地方都包含“ab”的项目。

相关问题