Regex capture lookbehind и lookahead

53
5

Я пытаюсь написать регулярное выражение для следующих ситуаций:

badword%
%badword
%badword%

Знаки % различаются в зависимости от того, где они находятся. A % спереди нуждается в том, чтобы соответствовать буквам, предшествующим слову "Слово", до badword пор, пока он не достигнет буквы, отличной от буквы. Аналогично, любой % который не находится на фронте, нуждается в поиске, чтобы соответствовать буквам, следующим за словом "слово", пока он не попадет в badword.

Вот чего я пытаюсь достичь. Если у меня есть следующее:

Просто регулярная суперсчетная справка.

badword   # should match "badword", easy enough
badword% # should match "badwording"
%badword% # should match "superbadwording"

В то же время. Если у меня есть аналогичное предложение:

Вот еще один пример с очень маленьким словом.

badword   # should match "badword", easy enough
badword% # should also match "badword"
%badword% # should match "verybadword"

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

Вот что я до сих пор на Java:

String badword  = "%badword%";
String _badword = badword.replace("%", "");
badword = badword.replaceAll("^(?!%)%", "(?=\w)"); // match a % NOT at the beginning of a string, replace with look ahead that captures \w, not working
badword = badword.replaceAll("^%", "(?!=\w)"); // match a % at the beginning of a string, replace it with a look behind that captures \w, not working
System.out.println(badword); // ????

Итак, как я могу это сделать?

PS: Пожалуйста, не предполагайте, что % вынуждены начинать и заканчивать матч. Если % - первый символ, тогда ему нужно будет посмотреть, все и все остальные % смотрят вперед.

спросил(а) 2013-12-07T13:49:00+04:00 6 лет, 5 месяцев назад
1
Решение
66

Из вашего вопроса не представляется нужным использовать lookaround, поэтому вы можете просто заменить все % на \w*

Snippet:

String tested = "Just a regular superbadwording sentece.";
String bad = "%badword%";
bad = bad.replaceAll("%", "\\\\w*");
Pattern p = Pattern.compile(bad);
Matcher m = p.matcher(tested);
while(m.find()) {
String found = m.group();
System.out.println(found);
}

\w не соответствует #, - и т.д. поэтому я думаю, что \S здесь лучше

ответил(а) 2013-12-07T14:42:00+04:00 6 лет, 5 месяцев назад
53

badword = badword.replaceAll("^%", "(?!=\w)"); 
// match a % at the beginning of a string, replace it with a look behind
//that captures \w, not working

(?!=\w) является негативным взглядом вперед для =\w, но кажется, что вы хотите получить положительный внешний вид. Во-вторых, lookaheads и lookbehind являются атомарными и, следовательно, по своей сути не захватывают, поэтому, если я прав в своей интерпретации, вы хотите:


"(?<=(\\w+))". Для захвата требуется дополнительное (). Для вашей первой части это будет: "(?=(\\w+)), а первый аргумент должен быть "(?<!^)%".

PS: Вам нужны две обратные косые черты для \\w, и вы, похоже, хотите совместить несколько символов, нет? Если это так, вам понадобится \\w+. Кроме того, если вы не хотите делать это для каждого события, я предлагаю использовать String.format() вместо replaceAll().

ответил(а) 2013-12-07T14:06:00+04:00 6 лет, 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема