下面有一个正则表达式'reg_replace('/(abc)(?!([^''"]''">[^<])<a> )/','$1',$content)'我想如果abc在锚定标记内,那么它不会被替换,但如果它在锚定标签外,那么它必须被替换E.g<a href="any@domain.com" title="adada" target="sdada">he is abc guy</a> is an abc guy etc...
在这种情况下,锚点标签内的abc不会被替换,但标签外的abc须被替换
您可以使用它来避免链接、脚本、样式、注释、cdata和标签属性中的内容:
$regex = '~(?:<(a|script|style)'b.*?</'1>|<!--.*?-->|<!'[CDATA'[.*?]]>|<.*?>)'
. '(*SKIP)(*FAIL)|abc~si';
$result = preg_replace($regex, 'HiHa!!', $content);
当子字符串与(*SKIP)
回溯控制谓词之前的子模式匹配,并且如果子模式在(*SKIP)
之后失败,正则表达式引擎不会尝试将子字符串与模式的另一部分(此处的另一个部分是abc
)匹配,而是在子字符串之后继续。(*FAIL)
强制子模式失败。
s
修饰符允许点与换行符匹配。
模式可以优化为:
$regex = '~(?><(a|script|style)'b(?>[^<]++|<(?!/'1>))*+</'1>|'
. '<!--(?>[^-]++|-(?!->))*+-->|'
. '<!'[CDATA'[(?>[^]]++|](?!]>))*+]]>|<[^>]*+>)++(*SKIP)(*FAIL)|abc~si';
更合适的方法
由于您正在尝试修改html文档,因此可以使用DOMDocument和XPath,它们是为这类任务设计的工具:
$doc = new DOMDocument();
@$doc->loadHTML($content);
$xpath = new DOMXPath($doc);
$textnodes = $xpath->query('//text()[not(ancestor::a)]');
foreach ($textnodes as $textnode) {
$textnode->nodeValue = str_replace('abc', 'HiHa!!', $textnode->nodeValue);
}
$result = $doc->saveHTML();
print_r($result);