如何否定Java中的任何正则表达式

时间:2011-12-22 23:12:29

标签: java regex regex-negation

我有一个我想要否定的正则表达式,例如

/(.{0,4})

String.matches返回以下内容

"/1234" true
"/12" true
"/" true
"" false
"1234" false
"/12345" false

有没有办法否定(仅使用regx)以上结果:

"/1234" false
"/12" false
"/" false
"" true
"1234" true
"/12345" true

我正在寻找一种适用于任何regx的通用解决方案,而无需重写整个正则表达式。

我看过以下内容 How to negate the whole regex?使用(?!pattern),但这对我来说似乎不起作用。

以下regx

(?!/(.{0,4}))

返回以下内容:

"/1234" false
"/12" false
"/" false
"" true
"1234" false
"/12345" false

这不是我想要的。 任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:27)

您需要添加锚点。原始正则表达式(减去不需要的括号):

/.{0,4}

...匹配包含斜杠的字符串,后跟0到4个字符。但是,因为你正在使用matches()方法,它会自动锚定,就像它真的一样:

^/.{0,4}$

为了达到相反的目的,你不能依靠自动锚定;你必须至少在前瞻中明确表示结束锚。您还必须使用.*“填充”正则表达式,因为matches()要求正则表达式使用整个字符串:

(?!/.{0,4}$).*

但我建议您明确地锚定整个正则表达式,如下所示:

^(?!/.{0,4}$).*$

它没有任何害处,它使您的意图非常清晰,特别是对于那些从Perl或JavaScript等其他版本学习正则表达式的人。 matches()方法的自动锚定非常不寻常。

答案 1 :(得分:1)

我知道这是一个非常老的问题,但希望我的回答可以帮助将来寻找此问题的任何人。

Alan Moore的答案几乎是正确的。您也需要将整个正则表达式分组,否则可能会锚定原始正则表达式的一部分。

例如,如果要否定以下正则表达式:abc|def(与"abc""def"匹配

添加(?!和添加$).*。您将以(?!abc|def$).*结尾。

此处的锚点仅适用于def,这意味着"abcx"在应该匹配时将不匹配。

我宁愿在(?!(?:之前加上)$).*

String negateRegex(String regex) {
    return "(?!(?:" + regex + ")$).*";
}

根据我的测试,看起来negateRegex(negateRegex(regex))的功能确实与regex相同。