Подтвердить что ты не робот

Обратные ссылки в 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?

И если нет, можете ли вы всегда работать с ним, используя этот вложенный просмотр? Существуют ли другие общепринятые методы?

4b9b3361

Ответ 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 между двумя повторяющимися символами!