【问题标题】:Regex for glossary replace用于词汇表替换的正则表达式
【发布时间】:2012-04-01 06:01:58
【问题描述】:

我正在编写词汇表模块 - 它必须在文本中找到已知单词并用链接替换它。如果是链接 ancor (<a href="...">word</a>) 或属性 (<span class="word">...</span>),则不能替换 word。

我已经写了代码:

$x = '<div>DVB-S2. DVB-S. DVB-S2DVB-S <sss DVB-S2 /> DVB-S2 <a href="dd">DVB-S2</a> DVB-S2 Hot bird 6/Hot Bird 8/Hot bird 9, 13.0</div>';

$word = 'Hot Bird 8';
$x = preg_replace("'(?<=[\s\>])(" . $word . ")(?=[^\d\w\-])(?!([^<]+)?>)'is", "<a href=\"s2\">$1</a>", $x);

$word = 'DVB-S2';
$x = preg_replace("'(?<=[\s\>])(" . $word . ")(?=[^\d\w\-])(?!([^<]+)?>)'is", "<a href=\"s2\">$1</a>", $x);

echo $x;

但它会将&lt;a href="dd"&gt;DVB-S2&lt;/a&gt; 替换为&lt;a href="dd"&gt;&lt;a href="s2"&gt;DVB-S2&lt;/a&gt;&lt;/a&gt;

我该如何解决?

【问题讨论】:

  • 我测试了你的代码,我注意到第一个 preg_replace 没有做任何事情
  • 更重要的是第二个正则表达式,以及锚替换问题。
  • 如果原来的a标签存在,你要替换它吗?
  • 所以表达式必须找到并替换 DVB-S2 的所有实例,除了 标记中已经存在的实例?

标签: php regex preg-replace


【解决方案1】:

这就是我得到的,我希望它有效

   echo preg_replace("@((?!<a\s*[^<>]*>.*?))($word)((?!</a>.))@i",'$1<a href="">$2</a>$3',$html) . chr(10);

哪个会输出

<div><a href="">DVB-S2</a>. DVB-S. <a href="">DVB-S2</a>DVB-S <sss <a href="">DVB-S2</a> /> <a href="">DVB-S2</a> <a href="dd">DVB-S2</a> <a href="">DVB-S2</a> Hot bird 6/Hot Bird 8/Hot bird 9, 13.0</div>

【讨论】:

  • 非常感谢 - 它有效。我对其进行了编辑以修复:&lt;sss &lt;a href=""&gt;DVB-S2&lt;/a&gt; /&gt; 收件人:@((?!&lt;a\s*[^&lt;&gt;]*&gt;.*?))($word)((?=[^&lt;&gt;\s])(?!&lt;/a&gt;.))@i
【解决方案2】:

你需要把它分解成三个规则:

  1. 单词两边由非单词字符或 BO[SL]/EO[SL] 分隔。
  2. 单词不在 之间。
  3. 单词不在和之间。

我们需要对规则 (1) 进行积极的前瞻和后瞻:

(?<=^|\W)word(?=\W|$)

\W 捕获非单词字符,因此除了字母、数字和下划线之外的任何字符。这与您的版本不完全相同,但您可以根据需要进行调整。 \b 也可能是一个不错的选择,在这种情况下,您不需要插入符号和美元符号。

现在,为规则 (2) 添加一个否定的后视:

(?<!<[^>]*)(?<=^|\W)(DVB-S2)(?=\W|$)

当单词前面有 &lt; 和任何非&gt; 字符时,即当它位于任何 HTML 标记的中间时,这会阻止匹配。

现在,为规则 (3) 添加负前瞻:

(?<!<[^>]*)(?<=^|\W)(DVB-S2)(?=\W|$)(?!</a>)

当单词 立即 后跟 &lt;/a&gt; 时,这会阻止匹配。这不是一个完美的解决方案,因为该单词可能不是链接文本的唯一部分,但它可能与您的情况足够接近,并且它通过了您的测试用例。在单个表达式中可能有比这更精确的方法,但目前没有想到。

以上所有内容都是用 .NET 方言正则表达式编写的,我假设 PHP 足够相似,可以为您工作。

【讨论】:

  • 谢谢,但它不起作用:编译失败:lookbehind assertion is not fixed length at offset 10
  • 还是谢谢你 - 你的回答对于理解技术非常有用。
猜你喜欢
  • 2019-10-24
  • 1970-01-01
  • 2017-09-09
  • 1970-01-01
  • 2022-12-10
  • 2019-01-24
  • 2015-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多