用于替换字符串中两个不同单词之间的单词的正则表达式
Regex expression to replace a word between two differents words in a string
我想使用正则表达式将两个单词 MNO
和 XYZ
之间的单词 ABC
替换为 ''
,但不会出现单词 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
之间的三个。
我在 PHP 中的 preg_replace
中尝试了一些正则表达式,但没有成功。
例如,在这个中,我不知道如何不匹配所有但 ABC
:
/(?<=MNO)(.*)ABC(.*)(?=XYZ)/g
我希望在这种情况下使用正则表达式和 preg_replace
。
有什么想法吗?
谢谢
如果 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;
您可以使用 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);
这里,(MNO)(.*?)(XYZ)
匹配并捕获MNO
,都在MNO
和XYZ
之间
然后 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
.
我想使用正则表达式将两个单词 MNO
和 XYZ
之间的单词 ABC
替换为 ''
,但不会出现单词 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
之间的三个。
我在 PHP 中的 preg_replace
中尝试了一些正则表达式,但没有成功。
例如,在这个中,我不知道如何不匹配所有但 ABC
:
/(?<=MNO)(.*)ABC(.*)(?=XYZ)/g
我希望在这种情况下使用正则表达式和 preg_replace
。
有什么想法吗? 谢谢
如果 MNO
和 XYZ
在句子中只出现一次,这将起作用。
试试这个正则表达式:
ABC(?!.*MNO)(?=.*XYZ)
用空白字符串替换每个匹配项
解释:
ABC
- 匹配ABC
(?!.*MNO)
- 否定前瞻以确保当前匹配后面没有跟在字符串 后面的某个地方 (?=.*XYZ)
- 正向前瞻以确保当前匹配后跟在字符串 后面某处的
MNO
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);
这里,(MNO)(.*?)(XYZ)
匹配并捕获MNO
,都在MNO
和XYZ
之间
然后 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
.