Java RegEx отрицательный lookbehind


У меня есть следующий код Java:

Pattern pat = Pattern.compile("(?<!function )\w+");
Matcher mat = pat.matcher("function example");
System.out.println(mat.find());

Почему mat.find() возвращает true? Я использовал отрицательный lookbehind, и example предшествует function. Не следует ли его выбросить?

3 15

3 ответа:

Посмотрите, чему он соответствует:

public static void main(String[] args) throws Exception {
    Pattern pat = Pattern.compile("(?<!function )\\w+");
    Matcher mat = pat.matcher("function example");
    while (mat.find()) {
        System.out.println(mat.group());
    }
}

Вывод:

function
xample
Поэтому сначала он находит function, которому не предшествует "function". Затем он находит xample, которому предшествует function e и поэтому не "function".

Предположительно вы хотите, чтобы шаблон соответствовалвсему тексту, а не просто находил совпаденияв тексте.

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

^(?<!function )\\w+$

Я предпочитаю второй подход, так как он означает, что шаблон сам определяет свою область соответствия, а не область, определяемую его использованием. Однако это всего лишь вопрос предпочтения.

Ваша строка имеет слово "function", которое соответствует \w+, и не предшествует "function".

Обратите внимание на две вещи:

  • Вы используете find(), который возвращает true для подстроки.

  • Из-за вышесказанного "функция" совпадает, поскольку ей не предшествует "функция".
    Вся строка никогда бы не совпала, потому что ваше регулярное выражение не совпадало. включите пробелы.

Вместо этого используйте Mathcher#matches() или ^ и $ якоря с отрицательным lookahead:

Pattern pat = Pattern.compile("^(?!function)[\\w\\s]+$"); // added \s for whitespaces
Matcher mat = pat.matcher("function example");

System.out.println(mat.find()); // false