2

我正在寻找一个正则表达式(php)来查找/替换网页中的一些单词。但是,它不能替换所有html标签之间的单词,只能在:斜体< i >、粗体< b >和纯文本之间。

例子:

单词:“你好”(不区分大小写)

<a href="#">Hello</a> im a writer that i like to say hello everyday. <b>Hello</b> Spiderman.

Replaces:在anchor中不能replace,只有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 没有很好地创建

任何人都知道为什么不能正常工作?谢谢。

4

1 回答 1

2

尝试这些模式的组合

$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.

您的问题的注释

解释

参见上面关于断言的链接:?<!对于否定的lookbehind断言不能用于匹配<a href="#">,因为它不是固定长度并导致编译错误。因此我在你好之后使用了前瞻断言?!来匹配。</a>开头和结尾的括号包括任何周围的 HTML 标记,因此除了以下</a>断言之外的所有内容都将被替换。

避免标签内hello替换的技巧是将它们替换为一些唯一的字符串(例如!X!),然后进行原始替换,然后将!X!for hello替换回来。它可能不是最好的解决方案,但它确实有效。

为什么你的正则表达式不起作用

您使用/I了修饰符(在模式的末尾)。修饰符区分大小写,/i表示不区分大小写,参见修饰符列表。我相信\b您的模式中的(单词边界)是多余的。

于 2013-05-07T11:12:31.570 回答