我正在寻找一个正则表达式(php)来查找/替换网页中的某些单词。但是,它不能替换所有 html 标签之间的单词,只能替换:斜体 <i>、粗体 <b> 和纯文本之间的单词。
示例:
单词:“hello”(不区分大小写)
<a href="#">Hello</a> im a writer that i like to say hello everyday. <b>Hello</b> Spiderman.
替换: anchor 中无法替换,只能替换 hello 和 < b>Hello< /b>
可以更换。
我测试了一些正则表达式,但没有一个能正常工作:
1) 来自 SMART SEO LINKS(WP 插件)
$reg = '/(?!(?:[^<\[]+[>\]]|[^>\]]+<\/a>))\b($word)\b/Imsu';
有时效果不好,删除内容并放置符号“>” 我对这个正则表达式做了一些修改,删除了“?!”或“?:”(我不知道是什么意思),但停止工作。
2)我尝试过的其他:
$reg = "/<([\w]+)[^>]*>\b('.$word.')\b<\/\1>/Imsu";
$reg = '/<+\s*\/\s\b('.$word.')\b[^>]\/\s>+/I';
不替换任何东西
$reg = '/<(\w+)[^>]*>\b('.$name.')\b<\/\1>/Imsu';
有时有效。
事实是,我不是正则表达式专家,我进行了几天测试,试图创建一个新的正则表达式,但没有达到我需要的结果。
事实是,替换将在 WP 插件中使用,这有时会影响模板或其他插件,或者 DOM 没有很好地创建
有人知道为什么不能正常工作吗?谢谢。
最佳答案
尝试组合这些模式
$reg = '/(?:<(\w+)[^>]*>)?\bhello\b(?!<\/a>)(<\/\\1>)?/i';
$reg0 = '/<\w[^>]*\bhello\b[^>]*>/Ui';
示例
$word = preg_quote('hello','/'); // to avoid PCRE injection
$str = '<a href="hello.php">Hello</a> I say hello everyday. <b>Hello</b> Spiderman.';
$reg = '/(?:<(\w+)[^>]*>)?\b'.$word.'\b(?!<\/a>)(<\/\\1>)?/i';
$reg0 = '/<\w[^>]*\b'.$word.'\b[^>]*>/Ui';
function handler($m) { return str_replace($GLOBALS["word"],'!X!',$m[0]); }
$str = preg_replace_callback($reg0,'handler',$str); // replace "hello" for say !X! inside tags
$str = preg_replace($reg,'[deleted]',$str); // delete "hello" elsewhere
$str = str_replace('!X!',$word,$str); // put "hello" inside tag back
print_r($str);
结果
<a href="hello.php">Hello</a> I say [deleted] everyday. [deleted] Spiderman.
问题注释
- ?! 是 look ahead assertion
- ?: 是 non-capturing subpattern
- U(大U)是非贪婪匹配
说明
请参阅上面有关断言的链接:?<!
对于否定的lookbehind断言不能用于匹配<a href="#">
,因为它不是固定长度并导致编译错误。因此我使用了前瞻断言 ?!
匹配</a>
你好之后。开头和结尾的括号包含任何周围的 HTML 标记,因此除了 </a>
之外的所有内容断言被替换。
避免标记内 hello 替换的技巧是将它们替换为某些唯一的字符串(例如 !X!
),然后进行原始替换,然后替换回 !X!
。回复你好。这可能不是最好的解决方案,但它确实有效。
为什么你的正则表达式不起作用
您使用了/I
修饰符(在模式的末尾)。修饰符区分大小写,/i
表示不区分大小写的评估,请参阅 the list of modifiers 。我相信\b
您的模式中的(字边界)是多余的。
关于php - 正则表达式替换网页中的单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16417189/