Вопрос по java, regex, null – Java RegEx, который соответствует чему-либо, НО буквальная строка 'NIL' или 'nil'

8

Хорошо, ребята. Вот вопрос типа интервью на 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!

+1 за ту часть, которая выделена курсивом, приятель Кресло Бронко. Kaz

Ваш Ответ

2   ответа
5

которое напрямую указывает конечный автомат, который может поочередно кормить символы строки и будет достигать состояния принятия, если строка не является вариантом в 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.

Вы можете указать это в своих «ведущих разработчиках». трубка и пусть он пока курит, хаха. :)
Спасибо за отзыв, Каз. Не уверен, курит ли он, но я позабочусь, чтобы он почувствовал запах этого нового табака. Я ценю альтернативный подход, а также объяснение. Armchair Bronco
18

негативный взгляд.

При включенной опции без учета регистра:

^(?!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).*

Принимая это как ответ. Обратите внимание, что мы добавили (? I) перед RegEx сразу после & quot; ^ & quot; Armchair Bronco
Согласно одному из ведущих разработчиков по этой проблеме, код в вашем первом примере ^ (?! nil $). * Будет работать, если его изменить следующим образом: & quot; ^ (? I) (?! nil $). * Extra бит впереди необходим, потому что у нас нет контроля над параметрами компилятора, поэтому RegEx должен выполнять эту работу сам. Armchair Bronco
@ArmchairBroncoNote that we added (?i) Да, именно поэтому Эндрю сказалenable case-insensitive matching, Есть два способа сделать это в Java:(?i) а такжеPattern.CASE_INSENSITIVE

Похожие вопросы