PHP Regex匹配字符串中的单词,不包括一个特定单词

时间:2011-09-22 12:12:18

标签: php regex replace expression

我有一个文本($ txt),一个单词数组($ words)我想添加一个必须不替换的链接和一个单词($ wordToExclude)。

$words = array ('adipiscing','molestie','fringilla');
$wordToExclude = 'consectetur adipiscing';


$txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque
mattis tincidunt dolor sed consequat. Sed rutrum, mauris convallis bibendum 
dignissim, ligula sem molestie massa, vitae condimentum neque sem non tellus.
Aenean dolor enim, cursus vel sodales ac, condimentum ac erat. Quisque
lobortis libero nec arcu fringilla imperdiet. Pellentesque commodo, 
arcu et dictum tincidunt, ipsum elit molestie ipsum, ut ultricies nisl
neque in velit. Curabitur luctus dui id urna consequat vitae mattis
turpis pretium. Donec nec adipiscing velit.'

我想获得这个结果:

$txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque
mattis tincidunt dolor sed consequat. Sed rutrum, mauris convallis bibendum 
dignissim, ligula sem <a href="#">molestie</a> massa, vitae condimentum neque sem non tellus.
Aenean dolor enim, cursus vel sodales ac, condimentum ac erat. Quisque
lobortis libero nec arcu <a href="#">fringilla</a> imperdiet. Pellentesque commodo, 
arcu et dictum tincidunt, ipsum elit <a href="#">molestie</a> ipsum, ut ultricies nisl
neque in velit. Curabitur luctus dui id urna consequat vitae mattis
turpis pretium. Donec nec <a href="#">adipiscing</a> velit.'

3 个答案:

答案 0 :(得分:3)

$result = preg_replace(
    '/\b                 # Word boundary
    (                    # Match one of the following:
     (?<!consectetur\s)  #  (unless preceded by "consectetur "
     adipiscing          #  adipiscing
    |                    # or
     molestie            #  molestie
    |                    # etc.
     fringilla
    )                    # End of alternation
    \b                   # Word boundary
    /ix', 
    '<a href="#">\1</a>', $subject);

答案 1 :(得分:2)

Okie doke!虽然我认为这在技术上是可行的,但我提供的解决方案在这一点上有点软:

s%(?!consectetur adipiscing)(adipiscing|molestie|fringilla)(?<!consectetur adipiscing)%<a href="#LinkBasedUpon$1">$1</a>%s

...转动

  

坐下来, consectetur adipiscing elit。 Quisque ... ligula sem molestie massa ... nec arcu fringilla imperdiet ... nec adipiscing velit。

...成

  坐下来,精神恍惚。 Quisque ... ligula sem <a href="#LinkBasedUponmolestie"> molestie </a> massa ... nec arcu <a href="#LinkBasedUponfringilla"> fringilla </a> imperdiet。 .. nec <a href="#LinkBasedUponadipiscing"> adipiscing </a> velit。

它是一个软解决方案的原因是它不处理部分单词或其他情况,其中要排除的单词不会以其中一个要匹配的单词开头或结尾。例如,如果我们要附加到被排除的“单词”(即consectetur adipiscing elit),则此表达式最终会匹配adipiscing中的consectetur adipiscing elit,因为adipiscing无法开始或与consectetur adipiscing elit

结尾相同

只要您的排除“字词”(A B C)始终以其中一个字词(C|X|E中包含C)结束或开头,它就应该有用,并且A B C以单词C结尾,因此应该有效...)

编辑{

“不匹配”单词必须以匹配单词之一开头或结尾的原因是此解决方案在匹配前使用负前瞻,并在匹配后使用负后瞻,以确保匹配的序列与单词不匹配不匹配(这有意义吗?)

<强>}

对此有一些解决方案,但它们是处理器和编程工作密集型中的一个或两个,并且取决于单词列表的大小和搜索文本的长度以及特定要求而呈指数级增加 - 并且您从来没有指定任何其他内容,所以我现在不打算进入它。如果这对你的情况足够好,请告诉我!

答案 2 :(得分:0)

我看到你是用PHP做的。我知道你在文本中找到了ARRAY字样,你需要用链接替换它们。此外,您还需要在替换时排除一个字符串。也许不是写出清晰而干净但复杂的正则表达式而是这个实用的,尽管可能不是最好的解决方案:

您将任务拆分为子任务:

  1. 使用preg_match_all查找排除字符串的所有匹配项的偏移量(您知道字符串长度(strlen)和PREG_OFFSET_CAPTURE的{​​{1}}标记,您将确定准确的开始和结束 - 如果有多个)
  2. 在您的单词列表上执行操作并再次使用preg_match_all来获取您需要用链接替换的所有单词
  3. 将您在步骤2中找到的位置与在步骤1中找到的位置进行比较,如果它们在外面,则进行替换或跳过,如果您出现重叠
  4. 它肯定不会是单行,但代码很容易,后来也很容易阅读。