奇怪的PHP preg_replace结果

Weird PHP preg_replace result

提问人:kim li 提问时间:4/15/2023 最后编辑:bobble bubblekim li 更新时间:4/25/2023 访问量:40

问:

$pedit =<<<head
 <div class="item"><div var="i_name_10">white gold</div> <div var="i_price_10">$5.99</div></div> 
head;

  $pedit = preg_replace("/(<.*var=\"i_name_10\".*>)(.*)(<\/.*?>\s*)/","$1"."aaa"."$3",str_replace("> <","><",$pedit));

结果:

white gold
$5.99
aaa

预期结果是

aaa
$5.99

当我在“白金”div 之后的换行符后放一个换行符或在图案后放一个 U 时,它就会按预期工作。但是,如果字符串重复并且更长,则这些解决方案似乎有问题或不干净。请帮忙!/U

白金替换为 AAA,而不是在末尾附加 AAA。

预期结果是

aaa
$5.99
php 正则表达式 preg-replace

评论

0赞 F.Igor 4/15/2023
您是否也希望剥离标签(结果中没有 HTML)并仅保留文本和数字?

答:

1赞 Wongjn 4/15/2023 #1

问题解释

默认情况下,正则表达式匹配将尽可能贪婪。这意味着第一个捕获组中的部分将比您预期的匹配更多。.*

对于 ,这匹配:<.*var=\"i_name_10\"

<div class="item"><div var="i_name_10"

然后我们有剩下的字符串:

>white gold</div> <div var="i_price_10">$5.99</div></div>

正则表达式的下一部分是 ,这可以吞噬所有:.*>

>white gold</div> <div var="i_price_10">$5.99</div>

因为下一部分,不能匹配任何东西,因为量词表示 0 或更多。(.*)*

我们现在有:

</div>

哪个匹配。(<\/.*?>\s*)

因此,我们的捕获组是

捕获 结果
(<.*var=\"i_name_10\".*>) <div class="item"><div var="i_name_10">white gold</div> <div var="i_price_10">$5.99</div></div>
(.*)
(<\/.*?>\s*) </div>

这就是为什么当您替换为 时,您将得到:"$1"."aaa"."$3"

<!-- $1 -->
<div class="item"><div var="i_name_10">white gold</div> <div var="i_price_10">$5.99</div></div>
<!-- /$1 -->
aaa
<!-- $3 -->
</div>
<!-- /$3 -->

溶液

但是,如果字符串重复并且更长,则这些解决方案似乎有问题或不干净

很难辨别你在这里所说的“字符串重复”是什么意思,哪个字符串重复?整个事情?同样对于“而且它更长”,你说的“它”具体是什么意思?

但是,不管这些注意事项如何,您似乎正在替换 HTML。因此,您可以使用最初提到的标志,或者可以在第一个捕获组中使用某种“手动”不贪婪,例如:<div var="i_name_10">white gold</div>U

"/(<[^>]+var=\"i_name_10\"[^>]*>)(.*)(<\/[^>]+?>\s*)/"

我们使用表达式来声明除了 之外的任何字符都可以,因此我们只在元素内部匹配,而不匹配“外部”元素。我们还使用 1 个或多个量词 () 而不是 0 或更多 (),因为 HTML 需要元素开头和结束标记中的元素名称。这减少了任何意外的机会。[^>]>+*

1赞 Sammitch 4/15/2023 #2

与其编写一个你自己在一夜睡眠后无法读取或修改的正则表达式,更不用说其他人了,不如使用专门设计用于解析和修改你所拥有的数据的工具。

$pedit =<<<'head'
 <div class="item"><div var="i_name_10">white gold</div> <div var="i_price_10">$5.99</div></div> 
head;

$d = new DOMDocument();
$d->loadHTML($pedit, LIBXML_HTML_NOIMPLIED);

// search for elements with the defined attribute, modify results
$xpath = new DOMXPath($d);
foreach($xpath->query('//div[@var="i_name_10"]') as $node)  {
    $node->nodeValue = 'aaa';
}

var_dump($d->saveHTML($d->documentElement));

输出:

string(88) "<div class="item"><div var="i_name_10">aaa</div> <div var="i_price_10">$5.99</div></div>"

编号: https://www.php.net/manual/en/book.dom.php