Ошибка регулярного выражения Java - группа просмотра назад не имеет очевидной максимальной длины

Я получаю такую ​​ошибку:

java.util.regex.PatternSyntaxException: Look-behind group does not have an
    obvious maximum length near index 22
([a-z])(?!.*\1)(?<!\1.+)([a-z])(?!.*\2)(?<!\2.+)(.)(\3)(.)(\5)
                      ^

Я пытаюсь сопоставить COFFEE, но не BOBBEE.

Я использую java 1.6.


person user963263    schedule 25.09.2011    source источник


Ответы (3)


Java не поддерживает переменную длину при просмотре назад.
В этом случае кажется, что вы можете легко проигнорировать это (при условии, что весь ваш ввод состоит из одного слова):

([a-z])(?!.*\1)([a-z])(?!.*\2)(.)(\3)(.)(\5)

Оба просмотра назад ничего не добавляют: первый утверждает, по крайней мере, два символа, тогда как у вас был только один, а второй проверяет, что второй символ отличается от первого, который уже был охвачен (?!.*\1).

Рабочий пример: http://regexr.com?2up96

person Kobi    schedule 25.09.2011
comment
Вероятно, неверно сказать, что Java не поддерживает переменную длину в поиске за регулярным выражением. Например, работает следующее: (?<=(a*))afs - person Rocky Inde; 27.04.2016

Чтобы избежать этой ошибки, вы должны заменить + регионом, например {0,10}:

([a-z])(?!.*\1)(?<!\1.{0,10})([a-z])(?!.*\2)(?<!\2.{0,10})(.)(\3)(.)(\5)
person luobo25    schedule 13.12.2011
comment
Я использовал это (? ‹= (OF [] {0,5}) | (MIRS [] {0,5})) [0-9] +, и он давал мне ту же ошибку. имеют очевидную максимальную длину около индекса 22, тогда после прочтения вашего комментария я изменил * на {0,5}, и он работал отлично. Интересно, почему Java не поддерживает это - person shabby; 17.08.2012
comment
В целом, это своего рода грязный обходной путь, но да, если кусок гарантированно не будет слишком длинным, просто замена + на что-то вроде {1,999} отлично работает. - person Nyerguds; 22.12.2020
comment
Обратите внимание: если вы заменяете +, вам следует начинать как минимум с 1, а не с 0. - person Nyerguds; 22.12.2020

Java делает шаг вперед, разрешая конечное повторение. Вы по-прежнему не можете использовать звездочку или плюс, но можете использовать вопросительный знак и фигурные скобки с указанным параметром max. Java определяет минимальную и максимальную возможную длину ретроспективного просмотра.
Предварительный просмотр в регулярном выражении (?<!ab{2,4}c{3,5}d)test имеет 6 возможных длин. Это может быть от 7 до 11 символов. Когда Java (версия 6 или более поздняя) пытается сопоставить ретроспективный поиск, он сначала возвращает минимальное количество символов (7 в этом примере) в строке, а затем, как обычно, оценивает регулярное выражение в ретроспективе слева направо. Если это не удается, Java отступает еще на один символ и пытается снова. Если ретроспективный просмотр продолжает терпеть неудачу, Java продолжает отступать до тех пор, пока ретроспективный просмотр не совпадет или не вернется максимальное количество символов (11 в этом примере). Этот повторяющийся шаг назад по строке объекта убивает производительность, когда количество возможных длин ретроспективного просмотра увеличивается. Имейте это в виду. Не выбирайте произвольно большое максимальное количество повторений, чтобы обойти недостаток бесконечных квантификаторов внутри ретроспективного обзора. В Java 4 и 5 есть ошибки, из-за которых в некоторых ситуациях ретроспективный просмотр с чередованием или переменными квантификаторами терпит неудачу, хотя в некоторых ситуациях это должно быть успешным. Эти ошибки были исправлены в Java 6.

Скопировано с Здесь

person boiledwater    schedule 30.05.2014