用于替换字符串中两个不同单词之间的单词的正则表达式

Regex expression to replace a word between two differents words in a string

我想使用正则表达式将两个单词 MNOXYZ 之间的单词 ABC 替换为 '',但不会出现单词 ABC 不在 MNOXYZ 之间。

例如,给定以下字符串:

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

所以唯一被替换的 ABCMNOXYZ 之间的三个。

我在 PHP 中的 preg_replace 中尝试了一些正则表达式,但没有成功。

例如,在这个中,我不知道如何不匹配所有但 ABC:

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

Here's a test link.

我希望在这种情况下使用正则表达式和 preg_replace

有什么想法吗? 谢谢

如果 MNOXYZ 在句子中只出现一次,这将起作用。

试试这个正则表达式:

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

用空白字符串替换每个匹配项

Click for Demo

解释:

  • 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;

您可以使用 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 demo

这里,(MNO)(.*?)(XYZ)匹配并捕获MNO,都在MNOXYZ之间 然后 XYZ 分成三组,在匿名函数内部,所有 ABC 仅在第二组中被替换。请注意,正则表达式末尾的 s 标志也是使 . 匹配换行符所必需的。

在第二个示例中,(?<=MNO) 是一个不消耗文本的正后视,并且要求 MNO 立即出现在当前位置的左侧,而 (?=XYZ) 是要求 XYZ 立即出现在当前位置右侧并且不消耗文本的正向前瞻,因此,此处不需要组。

preg_replace 更难:

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

参见regex demo

详情

  • (?:\G(?!\A)|MNO) - 上一场比赛结束或 MNO
  • (?:(?!MNO).)*? - 任何 1 个字符,出现 0 次或多次,尽可能少,不启动 MNO 字符序列
  • \K - 丢弃匹配缓冲区中文本的匹配重置运算符
  • ABC - 一个 ABC
  • (?=(?:(?!MNO).)*?XYZ) - 紧靠右边,必须有 0+ 个字符,尽可能少,不开始 MNO 字符序列后跟 XYZ.