替换术语表的Regex



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

我写过代码:

$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 . ")(?=[^dw-])(?!([^<]+)?>)'is", "<a href="s2">$1</a>", $x);
$word = 'DVB-S2';
$x = preg_replace("'(?<=[s>])(" . $word . ")(?=[^dw-])(?!([^<]+)?>)'is", "<a href="s2">$1</a>", $x);
echo $x;

但它取代了<a href="dd">DVB-S2</a>成为<a href="dd"><a href="s2">DVB-S2</a></a>

我该怎么修?

这就是我得到的,我希望它能在中工作

   echo preg_replace("@((?!<as*[^<>]*>.*?))($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>

您需要将其分解为三条规则:

  1. 单词两侧由非单词字符或BO[SL]/EO[SL]分隔
  2. Word不在<及其匹配>
  3. 单词不在和之间

我们需要一个积极的前瞻和前瞻规则(1):

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

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

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

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

当单词前面有<和任何非>字符时,即当它位于任何HTML标记的中间时,这可以防止匹配。

现在,为规则(3)添加一个负面展望:

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

当单词后紧跟</a>时,这将防止匹配。这不是一个完美的解决方案,因为单词可能不是链接文本的唯一部分,但它可能足够接近您的情况,并且通过了您的测试用例。可能有一种方法可以在一个表达式中比这更精确,但目前没有任何想法。

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

最新更新