Выражение регулярного выражения для замены слова между двумя разными словами в строке - PullRequest
0 голосов
/ 24 февраля 2019

Я хотел бы использовать регулярное выражение для замены слова ABC между двумя словами MNO и XYZ на '', но не вхождения слова ABC, которые не находятся между MNOи XYZ.

Например, с учетом следующей строки:

Lorem ABC ipsum ABC bla MNO bla ipsum ABC asfg 123 hello ABC dd ABC XYZ hello ABC

Ожидаемый результат будет:

Lorem ABC ipsum ABC bla MNO bla ipsum asfg 123 hello dd XYZ hello ABC

Таким образом, единственный ABC 'заменены три между MNO и XYZ.

Я пробовал некоторые выражения регулярных выражений в preg_replace в PHP, но у меня ничего не получилось.

Например, в этом я не знаю, как сопоставить не все, кроме ABC:

/(?<=MNO)(.*)ABC(.*)(?=XYZ)/g

Вот тестовая ссылка .

Буду признателен за использование регулярных выражений и preg_replace в этом случае.

Есть идеи?Спасибо

Ответы [ 2 ]

0 голосов
/ 24 февраля 2019

Вы можете использовать preg_replace_callback:

$s = preg_replace_callback('~(MNO)(.*?)(XYZ)~s', function($m) {
    return $m[1] . str_replace('ABC', 'XXX', $m[2]) . $m[3];
}, $s);

Или, с осторожностью, сделать код внутри анонимной функции немного более простым:

$s = preg_replace_callback('~(?<=MNO).*?(?=XYZ)~s', function($m) {
    return str_replace('ABC', 'XXX', $m[0]);
}, $s);

См. Демонстрация PHP

Здесь (MNO)(.*?)(XYZ) соответствует и захватывает MNO, все между MNO и XYZ, а затем XYZ в три группы и внутри анонимной функции, все ABCs заменяются только во второй группе.Обратите внимание, что флаг s в конце регулярного выражения также необходим для того, чтобы . соответствовал символам разрыва строки.

Во втором примере (?<=MNO) является положительным взглядом сзади, который не потребляет текст,и требует, чтобы MNO присутствовал непосредственно слева от текущего местоположения, а (?=XYZ) является положительным прогнозом, который требует, чтобы XYZ присутствовал немедленно справа от текущего местоположения, и также не потребляет текст, таким образом,здесь нет необходимости в группах.

С preg_replace:

preg_replace('~(?:\G(?!\A)|MNO)(?:(?!MNO).)*?\KABC(?=(?:(?!MNO).)*?XYZ)~s', 'XXX', $s)

гораздо сложнее. См. демонстрационную версию regex .

Подробности

  • (?:\G(?!\A)|MNO) - конец предыдущего матча или MNO
  • (?:(?!MNO).)*? - любой 1 символ, 0 или более вхождений, как можно меньше, который не запускает MNO последовательность символов
  • \K - оператор сброса совпадений, который сбрасывает текст в буфере совпадений
  • ABC - ABC
  • (?=(?:(?!MNO).)*?XYZ) - сразу направо, должно быть 0+ символов, как можно меньше, которые не запускаютсяпоследовательность символов MNO, за которой следует XYZ.
0 голосов
/ 24 февраля 2019

Это будет работать, если в предложении есть только одно вхождение MNO и XYZ.

Попробуйте это регулярное выражение:

ABC(?!.*MNO)(?=.*XYZ)

Замените каждое совпадение пустой строкой

Нажмите для демонстрации

Объяснение:

  • ABC - совпадения ABC
  • (?!.*MNO) - отрицательный просмотр, чтобы убедиться, что за текущим соответствием не следует MNO где-то позже в строке
  • (?=.*XYZ) - положительный просмотр, чтобы убедиться, чтоза текущим совпадением следует XYZ где-то позже в строке

Код ( RESULT )

$re = '/ABC(?!.*MNO)(?=.*XYZ)/m';
$str = 'Lorem `ABC` ipsum ABC bla MNO bla ipsum ABC asfg 123 hello ABC dd ABC XYZ hello ABC
';
$subst = '';
$result = preg_replace($re, $subst, $str);
echo "The result of the substitution is ".$result;
...