Способы исключить слово в регулярном выражении (без предварительного просмотра?) - PullRequest
3 голосов
/ 07 ноября 2019

Если у меня есть ввод:

hello cat
hellocat
hello gat

Я хотел бы найти строку, начинающуюся со слова "привет" и не имеющую слова "кошка" после него.

Можно ли отрицать группу, например:

hello[^(\s?cat)]

Или вы можете отрицать только набор символов в этой позиции? Если нет, каковы некоторые способы сделать это? Единственный способ, которым я смог сделать это, - это с позитивным взглядом:

hello(?!\s?cat)

Но мне было интересно, есть ли альтернативные подходы к этому.

Ответы [ 3 ]

3 голосов
/ 07 ноября 2019

Существует также другой способ без осмотра, который, я думаю, стоит упомянуть как интересную концепцию: /hello(?:\scat)|(hello\s.*)/

В этом случае мы сначала сопоставляем то, что нам не нужно (но не фиксируем это)) тогда мы только захватим вторую часть, если первая часть не удалась, что означает, что в захвате у вас всегда будет что-то, что не содержит cat.

. В этом примере вы можете проверить https://regex101.com/r/bydCGb/3,в поле информации о матче захват «группы 1», а также проверка замещающей части, у нас никогда не будет части «кошка».

В соответствии с вашим случаем вы можете сказать: если есть группа захвата 1, тосделай что-нибудь.

2 голосов
/ 07 ноября 2019

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

Вы можете исключить определенные символы, используя соглашение [^abc]. Однако вам придется явно исключить cat, но затем разрешить все, что почти cat.

Например,

((hello)ca[^t]|(hello)c[^a]|(hello)[^c])

Затем получить захваченную группу в пределах, соответствующей группе hello. Пробелы после приветствия и выбора этой опции делают ее немного сложнее. Этот необязательный пробел может быть захвачен следующим образом:

((hello)\sca[^t]|(hello)\sc[^a]|(hello)\s[^c]|(hello)ca[^t]|(hello)c[^a]|(hello)[^c ])

Примечание: у него есть все шесть опций, а последний добавляет необязательный пробел, чтобы гарантировать, что первые три не будут захвачены.

Проверено здесь: https://regex101.com/r/sgoHyJ/1

Полагаю, вы можете понять, почему они изобрели негативные прогнозы ...

2 голосов
/ 07 ноября 2019

Вы не можете легко сделать это с чистым регулярным выражением, не используя отрицательный взгляд. Однако, если вы выполняете эти вызовы регулярных выражений через API на каком-либо языке программирования, вы можете сформулировать совпадение, используя следующие положительные значения:

^hello\b.*

и следующие отрицательные значения:

^hello cat\b

То есть действительное совпадение положительно на первом шаблоне и отрицательно на втором шаблоне. В Java это предлагаемое решение будет выглядеть так:

String input = "hello gat";
if (input.matches("hello\\b.*") && !input.matches("hello cat\\b.*")) {
    System.out.println("MATCH");
}
else {
    System.out.println("NO MATCH");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...