如何否定Java中的任何正则表达式
Posted
技术标签:
【中文标题】如何否定Java中的任何正则表达式【英文标题】:how to negate any regular expression in Java 【发布时间】:2012-01-26 11:59:57 【问题描述】:我有一个想要否定的正则表达式,例如
/(.0,4)
which String.matches 返回以下内容
"/1234" true
"/12" true
"/" true
"" false
"1234" false
"/12345" false
有没有办法对上述内容进行否定(仅使用 regx),结果是:
"/1234" false
"/12" false
"/" false
"" true
"1234" true
"/12345" true
我正在寻找一种通用解决方案,它适用于任何正则表达式,而无需重写整个正则表达式。
我看过以下 How to negate the whole regex? 使用 (?! 模式),但这似乎对我不起作用。
以下正则
(?!/(.0,4))
返回以下内容:
"/1234" false
"/12" false
"/" false
"" true
"1234" false
"/12345" false
这不是我想要的。 任何帮助将不胜感激。
【问题讨论】:
你不能只匹配并否定它是否匹配吗?这是任何不重写正则表达式的正则表达式的通用解决方案。 这个匹配的编码是现有框架的一部分,如果不破坏其他东西就无法更改。 【参考方案1】:您需要添加锚点。原始正则表达式(减去不需要的括号):
/.0,4
...匹配包含一个斜线后跟零到四个字符的字符串。但是,因为您使用的是 matches()
方法,所以它会自动锚定,就好像它真的是:
^/.0,4$
要实现相反的效果,您不能依赖自动锚定;您必须至少在前瞻中明确结束锚点。您还必须使用.*
“填充”正则表达式,因为matches()
要求正则表达式消耗整个字符串:
(?!/.0,4$).*
但我建议您明确锚定整个正则表达式,如下所示:
^(?!/.0,4$).*$
它没有害处,它让你的意图非常清楚,尤其是对于那些从 Perl 或 javascript 等其他风格学习正则表达式的人。 matches()
方法的自动锚定非常不寻常。
【讨论】:
那么这适用于任何正则表达式吗?即String negateRegex(String regex) return "(?!" + regex + "$).*";
会按预期工作吗?这可以否定自己吗?即negateRegex(negateRegex(regex))
在功能上是否与regex
相同?
嗯,我在这里做了一些初步测试[1],它似乎在我尝试过的所有情况下都有效,包括否定否定。 [1]regexplanet.com/advanced/java/index.html
我不相信你可以像字符串一样操作正则表达式。你考虑 \Q 和 \E 吗?您是否考虑最后的反斜杠?【参考方案2】:
我知道这是一个非常古老的问题,但希望我的回答可以帮助任何将来寻找这个问题的人。
虽然Alan Moore 的回答几乎是正确的。您还需要对整个正则表达式进行分组,否则您可能会仅锚定原始正则表达式的一部分。
例如,如果您想否定以下正则表达式:abc|def
(匹配 "abc"
或 "def"
附加(?!
和附加$).*
。你最终会得到(?!abc|def$).*
。
这里的anchor只适用于def
,意思是"abcx"
应该不匹配。
我宁愿在(?!(?:
前面加上)$).*
。
String negateRegex(String regex)
return "(?!(?:" + regex + ")$).*";
从我的测试来看,negateRegex(negateRegex(regex))
在功能上确实与regex
相同。
【讨论】:
以上是关于如何否定Java中的任何正则表达式的主要内容,如果未能解决你的问题,请参考以下文章