Вопрос по java, regex, null – Java RegEx, который соответствует чему-либо, НО буквальная строка 'NIL' или 'nil'
Хорошо, ребята. Вот вопрос типа интервью на Java, который, кажется, озадачил некоторых очень умных людей здесь. Они действительно нуждаются в этом для производственного кода, так что это больше, чем просто головоломка для интервью.
Им нужно регулярное выражение в Java, которое возвращает true, если строковый литералanything кроме трехбуквенного слова NIL. Тест должен быть регистрозависимым, а сам RegEx должен выполнять всю работу.
Таким образом, RegEx должен отклонитьNIL, nil, NiL, nIL, и так далее.
Однако он должен принять: nile, anil, will, zappa-nil-a и пустую строку.
How many Java developers does it take to write a trivial RegEx? Apparently a lot!
которое напрямую указывает конечный автомат, который может поочередно кормить символы строки и будет достигать состояния принятия, если строка не является вариантом в NIL:
(|.|..|[^Nn]..|.[^Ii].|..[^Ll]|....+)
Это будет работать на классических движках регулярных выражений, которые не реализуют хакерские проверки и могут быть преобразованы в невероятно быстрый DFA.
Возможно, вам придется закрепить это^
а также$
в зависимости от того, какую функцию регулярного выражения вы используете с: (целой строкой) семантики соответствия или семантики поиска подстроки.
Например, grep test:
# rejects lines like nIl and NiL but accepts all else
# including blank lines:
grep -E '^(|.|..|[^Nn]..|.[^Ii].|..[^Ll]|....+)$'
Идея здесь такова:
All strings of length one, two, or four or more match. A three-character string matches if and only if: It does not begin with an N or n; or It does not have an I or i in the middle; or It does not have an L or l at the end.Отклонение NIL и Nil состоит в том, что они не выполняют все три правила 2.1, 2.2 и 2.3. NIL начинается с N, поэтому он терпит неудачу 2.1. У него действительно есть I в середине, поэтому у него не получается 2.2, и у него есть L в конце, поэтому у него не получается 2.3.
При включенной опции без учета регистра:
^(?!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).*
Note that we added (?i)
Да, именно поэтому Эндрю сказалenable case-insensitive matching, Есть два способа сделать это в Java:(?i)
а такжеPattern.CASE_INSENSITIVE