Исключить совпадение, если между двумя шаблонами есть слово

Есть файл:

cat file.txt
dog blah crocodile blah dog blah cat blah crocodile blah dog blah crocodile blah dog blah cat blah dog blah cat blah crocodile blah dog blah crocodile blah mice blah cat blah crocodile

Что я пытаюсь сделать достигать: каждое слово крокодил должно быть заменено, но не должно заменяться, если между словами собака (или мыши ) и крокодил есть слово cat

Примерно так:

dog blah replacement blah dog blah cat blah crocodile blah dog blah replacement blah dog blah cat blah dog blah cat blah crocodile blah dog blah replacement blah mice blah cat blah crocodile

Мой прогресс:

$txt = preg_replace('/((dog|mice)(.*?)(?:(?!cat))(.*?))crocodile/', "$1replacement", $txt);

Каждое бла слово означает что угодно.

0
задан 16 October 2019 в 22:00

1 ответ

После получения отзывов о Meta этот вопрос (к моему удивлению) относится к теме, поэтому я объясню одну рабочую технику.

Я нахожу ваше простое английское объяснение требований к шаблону немного нечетким, поэтому мне нужно уточнить, что мой шаблон:

  1. начнет потреблять, когда встретит слово dog или ] mice , затем
  2. он будет выполнять просмотр вперед на каждом шаге, выполняемом обработчиком регулярных выражений, чтобы гарантировать, что слова dog , mice и cat ] не найдены при поиске слова крокодил тогда
  3. ожидается пробел перед словом крокодил , затем
  4. используется метасимвол \ K для "освобождения" всех ранее использованных символов - это позволяет использовать только слово крокодил в качестве соответствия полной строки - которое будет заменено ... но проверка еще не завершена ... затем
  5. упреждающий просмотр используется для проверки того, что за квалифицирующей строкой крокодил не следует строка cat перед тем, как следовать собакой или мышами .

Шаблон:

 /(?:dog|mice)(?:(?!dog|mice|cat).)* \Kcrocodile(?= (?:(?!dog|mice|cat).)* (?:dog|mice))/

Замена:

Replacement

Код PHP: ( Демо )

$txt = 'dog blah crocodile blah dog blah cat blah crocodile blah dog blah crocodile blah dog blah cat blah dog blah cat blah crocodile blah dog blah crocodile blah mice blah cat blah crocodile';

echo preg_replace('/(?:dog|mice)(?:(?!dog|mice|cat).)* \Kcrocodile(?= (?:(?!dog|mice|cat).)* (?:dog|mice))/', 'replacement', $txt);
// output is identical to what is expected in your question.

Я не включаю какие-либо метасимволы границы слова, потому что мне трудно угадать из вашей сфабрикованной входной строки, если это необходимо. Есть вероятность, что включение в шаблон \ b повысит точность.

шт. некоторые примечания по синтаксису ...

  • (?: ...) - это группа без захвата
  • (?! ...) - это негативный прогноз.
  • (? = ...) - положительный прогноз.
0
ответ дан 19 April 2020 в 12:38

Другие вопросы по тегам:

Похожие вопросы: