【问题标题】:Complex pattern replacement using PHP preg_replace function ignoring quoted strings使用忽略引用字符串的 PHP preg_replace 函数进行复杂模式替换
【发布时间】:2010-05-12 05:21:13
【问题描述】:

考虑以下字符串:

这是一个字符串,其中一些关键字 可用。 '我需要格式化 来自 STRING 的关键字

在上面的字符串关键字是STRINGWHERE

现在我需要得到如下输出:

this is a <b>STRING</b> <b>WHERE</b> some keywords ARE available. 'i need TO format the KEYWORDS from the STRING'

这样 html 输出会是这样的:

这是一个STRING WHERE一些关键字 可用。 '我需要格式化 来自 STRING 的关键字

请注意,引号 ('...') 字符串中的关键字将被忽略。在上面的示例中,我忽略了引用字符串中的 STRING 关键字。

请提供以下 PHP 脚本的修改版本,以便我可以得到我想要的结果:

$patterns = array('/STRING/','/WHERE/');
$replaces = array('<b>STRING</b>', '<b>WHERE</b>');
$string   = "this is a STRING WHERE some keywords ARE available. 'i need TO format the KEYWORDS from the STRING'";
preg_replace($patterns, $replaces, $string);

【问题讨论】:

    标签: php string replace preg-replace design-patterns


    【解决方案1】:

    这将适用于您的字符串示例,但更复杂的字符串会出现问题,例如那些包含带撇号的单词。无论如何,它可以作为一个起点。

    $keywords = array("STRING", "WHERE");
    $regexp = '/(\'[^\']+\')|\b(' . implode('|', $keywords) . ')\b/e';
    preg_replace($regexp, "strlen('\\2') ? '<b>\\2</b>' : '\\0'", $string);
    

    【讨论】:

    • 哇!很好的解决方案。请您解释一下\b 和\\2 的含义。虽然,如果我考虑另一个引号,例如“包括”(表示两个引号),脚本会是什么?非常感谢... :)
    • \b - 单词边界,即字符串中一个字符是字母(或数字或“_”)的位置,另一个字符 - 不是字母。 \0, \1, \2 - 第 n 个带括号的模式捕获的文本: \1 - 第一对正则表达式括号的内容(在本例中 - 引用的子字符串),\2 - 第二对的内容 (在这种情况下 - 关键字之一),\0 - 整个匹配的字符串(在这种情况下它等于 \1 或 \2)
    • 但是根据 OP,此解决​​方案是否会忽略一对单引号中包含的文本?
    【解决方案2】:

    尝试类似:

    $keywords = array(
      'STRING' ,
      'WHERE' ,
      'KEYWORDS'
    );
    $keywordsRE = array();
    foreach( $keywords as $w ) {
      $keywordsRE[] = '/\b('.$w.')\b/';
    }
    $string = "this is a STRING WHERE some keywords KEYWORDS ARE available. 'i need TO format the KEYWORDS from the STRING'";
    $stringParts = explode( "'" , $string );
    foreach( $stringParts as $k => $v ) {
      if( !( $k%2 ) )
        $stringParts[$k] = preg_replace( $keywordsRE , '<b>$1</b>' , $v );
    }
    $stringReplaced = implode( "'" , $stringParts );
    

    重复相同的关键字(具有相同的更改)有点多余 - 使用正则表达式允许您将这些相同的更改(在这种情况下,将匹配项包装在 &lt;b&gt;&lt;/b&gt; 标记中)应用于所有匹配项。

    【讨论】:

    • 这是一个不完美的解决方案,而且有点 hacky,但它确实有效。我已经更改了$string 变量的内容以证明(即在排除区域内外都可以看到“关键字”)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多