Java RegEx匹配任何内容但是文字字符串’NIL’或’nil’
好,朋友们。 这是一个Java面试类型的问题,似乎已经让一些非常聪明的人难过了。 他们实际上需要这个用于生产代码,因此它不仅仅是一个采访益智游戏。
他们需要一个Java中的正则表达式,如果字符串文字不是3个字母的单词NIL,则返回true。 测试需要不区分大小写,RegEx本身必须完成所有工作。
因此,RegEx应该拒绝NIL,零,NiL,nIL等。
但是,它应该接受:nile,anil,will,zappa-nil-a和空字符串。
编写一个简单的RegEx需要多少Java开发人员? 显然很多!
你可以使用负向前瞻来做到这一点。
启用不区分大小写的选项:
^(?!nil$).*
如果你不需要在匹配中实际返回字符串,你可以在最后留下.*
。 这是一个没有不区分大小写的选项的版本:
^(?![nN][iI][lL]$).*
说明:
^ # start of string anchor (?! # start negative lookahead (fail if...) nil # literal characters 'nil' $ # end of string ) # end lookahead .* # consume string (not necessary, but it acts more like a typical regex)
如果你想让正则表达式匹配nil\n
,那么在前瞻中使用\z
代替$
: ^(?!nil\z).*
这是一个真正的正则表达式,它直接指定一个有限的自动机,可以逐个输入字符串的字符,如果字符串不是NIL的变体,它将达到接受状态:
(|.|..|[^Nn]..|.[^Ii].|..[^Ll]|....+)
这将适用于没有实现环视黑客攻击的经典正则表达式引擎,并且可以转换为极快的DFA。
您可能必须使用^
和$
来锚定它,具体取决于您使用的正则函数类型:(整个字符串)匹配语义或子字符串搜索语义。
例如,grep测试:
# rejects lines like nIl and NiL but accepts all else # including blank lines: grep -E '^(|.|..|[^Nn]..|.[^Ii].|..[^Ll]|....+)$'
这里的想法是:
- 长度为一,二或四或更多的所有字符串都匹配。
- 当且仅当以下情况时,三个字符的字符串匹配:
- 它不是以N或n开头; 要么
- 它中间没有I或i; 要么
- 它最后没有L或l。
如何拒绝NIL和Nil是因为它们都失败了所有三条规则2.1,2.2和2.3。 NIL确实以N开头,因此它失败了2.1。 它确实在中间有一个I,所以它失败了2.2,它最后确实有一个L,所以它失败了2.3。