Обратные ссылки в lookbehind
Можете ли вы использовать обратные ссылки в lookbehind?
Скажем, я хочу split
везде, где позади меня символ повторяется дважды.
String REGEX1 = "(?<=(.)\\1)"; // DOESN'T WORK!
String REGEX2 = "(?<=(?=(.)\\1)..)"; // WORKS!
System.out.println(java.util.Arrays.toString(
"Bazooka killed the poor aardvark (yummy!)"
.split(REGEX2)
)); // prints "[Bazoo, ka kill, ed the poo, r aa, rdvark (yumm, y!)]"
Использование REGEX2
(где обратная ссылка находится в lookahead, вложенном внутри lookbehind) работает, но REGEX1
дает эту ошибку во время выполнения:
Look-behind group does not have an obvious maximum length near index 8
(?<=(.)\1)
^
Этот тип смысла, я полагаю, потому что, как правило, backreference может захватывать строку любой длины (если компилятор regex немного умнее, он может определить, что \1
есть (.)
в этом случае, и, следовательно, имеет конечную длину).
Итак, есть способ использовать обратную ссылку в lookbehind?
И если нет, можете ли вы всегда работать с ним, используя этот вложенный просмотр? Существуют ли другие общепринятые методы?
Ответы
Ответ 1
Похоже, ваше подозрение верно, что обратные ссылки вообще не могут использоваться в Java lookbehinds. Обходной путь, который вы предложили, делает конечную длину lookbehind явной и выглядит очень умно для меня.
Мне было интересно узнать, что делает Python с этим регулярным выражением. Python поддерживает только lookbehind с фиксированной длиной, а не с конечной длиной, как Java, но это регулярное выражение является фиксированной длиной. Я не мог использовать re.split()
напрямую, потому что Python re.split()
никогда не разбивается на пустое совпадение, но я думаю, что нашел ошибку в re.sub()
:
>>> r=re.compile("(?<=(.)\\1)")
>>> a=re.sub(r,"|", "Bazooka killed the poor aardvark (yummy!)")
>>> a
'Bazo|oka kil|led the po|or a|ardvark (yum|my!)'
Взаимосвязь lookbehind между двумя повторяющимися символами!