Php preg_replace替换两个标记之间的所有匹配内容,但另外两个特定标记中包含的内容除外

时间:2018-02-26 07:10:29

标签: php regex preg-replace

我有这个HTML:

(text)Text one(/text)(text)text two(/text)<input type="text" name="name" 
id="name" value="(text)text three(/text)" />(text)Text four(/text)

我想替换(text)和(/ text)之间包含的单词和相对(text)(/ text)标签,但输入/ textarea值中包含的标签除外。

我想使用正则表达式,而不是dom

实际上我正在使用:

preg_replace("~\\(text\)[\s\S]+?\\(\/text\)~","replacing text",$content);

但是这个替换所有内容,也包含输入内容/ textareas

由于

1 个答案:

答案 0 :(得分:0)

您可以实施(*SKIP)(*FAIL)技术以匹配<input...>标记,并取消其替换资格。这将允许所有(text)...(/text)子字符串按预期替换。

Pattern&Replacement Demo

代码:(Demo

$html=<<<HTML
(text)Text one(/text)(text)text two(/text)<input type="text" name="name" 
id="name" value="(text)text three(/text)" />(text)Text four(/text)
HTML;

echo preg_replace('~<input[^>]+>(*SKIP)(*FAIL)|\(text\).*?\(/text\)~','[*]',$html);

输出:

[*][*]<input type="text" name="name" 
id="name" value="(text)text three(/text)" />[*]

...现在为精美印刷

  • 通常不建议使用正则表达式解析html,因为它会工作直到突然/默默地由于输入字符串本身的边缘情况/异常而无法工作。像DomDocument这样的html解析器通常是推荐的工具。
  • 我不确定您是否正在执行任何动态替换文本,或者是否所有替换都接收到相同的静态值。如果您需要执行动态替换,preg_replace_callback()可能是此工作的最佳工具。
  • 我的模式非常适合您的输入字符串。根据实际项目中数据的可变性,可能需要对模式进行细化/调整。
  • 我的模式在.*?(text)之间使用(/text)以允许(字符的可能性。如果您知道,这些相对位置中不会有(,您可以使用[^(]*来提高模式效率。输入标记部分中的[^>]+也是如此 - 如果您的项目数据在这些标记中包含>,那么您可以使用.*?,但效率会降低。