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

2022-09-03 16:47:41

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

/(.{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。

我已经看了下面的如何否定整个正则表达式?使用(?!模式),但这似乎对我不起作用。

以下注册表

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

返回以下内容:

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

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


答案 1

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

/.{0,4}

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

^/.{0,4}$

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

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

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

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

它没有害处,它让你的意图非常清楚,特别是对于那些从其他风格(如Perl或JavaScript)学习正则表达式的人来说。该方法的自动锚定是非常不寻常的。matches()


答案 2

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

虽然艾伦·摩尔的答案几乎是正确的。您还需要对整个正则表达式进行分组,否则您将面临仅锚定原始正则表达式的一部分的风险。

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

预置和追加 。您最终会得到 .(?!$).*(?!abc|def$).*

这里的锚点只适用于 ,这意味着当它应该匹配时不会匹配。def"abcx"

我宁愿在前面和后面附加。(?!(?:)$).*

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

从我的测试来看,它看起来确实在功能上与.negateRegex(negateRegex(regex))regex