preg_match_all 与使用相同模式的 preg_replace 有不同的结果集

preg_match_all has different result set than preg_replace using the same pattern

我发现 preg_match_all 和 preg_replace 没有找到基于相同模式的相同匹配项。

我的模式是:

/<(title|h1|h2|h3|h4|h5|ul|ol|p|figure|caption|span)(.*?)><\/()>/

当我 运行 这是针对包含

之类的片段时
<span class="blue"></span> 

与 preg_match_all 我得到 17 场比赛。

当我在 preg_replace 中使用相同的模式时,我得到 0 个匹配项。用选择列表替换 \1 确实找到了匹配项,但当然这不能作为解决方案,因为它不能确保结束标记与开始标记的类型相同。

总体目标是找到没有内容的标签实例,如果没有内容就不应该出现...我向你保证,这是一场圣战。

在测试正则表达式是否有效时,我也在 php cli 中尝试过。这是输出:

Interactive shell

php > $str = 'abc<span class="blue"></span>def';
php > $pattern = "/<(title|h1|h2|h3|h4|h5|ul|ol|p|figure|caption|span)(.*?)><\/()>/";
php > $final = preg_replace($pattern, '', $str);
php > print $final;
abc<span class="blue"></span>def
$str = 'abc<span class="blue"></span>def';
$pattern = "/<(title|h1|h2|h3|h4|h5|ul|ol|p|figure|caption|span)(.*?)><\/(\1)>/";
                                                              // added \  ^
$final = preg_replace($pattern, '', $str);
print $final;
// echos 'abcdef'

说明:

"" // <-- character in octal notation

非常不同
'' // <-- backslash and 1

因为第一个是转义序列。这也是我几乎只使用单引号字符串的原因。见 http://php.net/string#language.types.string.syntax.double