需要计算匹配并替换" nth"使用preg_replace_callback进行匹配

时间:2014-03-28 21:31:20

标签: php regex replace preg-replace-callback

我需要搜索一些内容并用HTML包含某些单词。要搜索的单词是在一个数组中,我想只替换每组匹配的第二个到最后一个匹配项。所以,作为一个例子,如果有5场比赛,我想替换第4场比赛。如果有3场比赛,请更换第2场比赛。如果有2个匹配项,则替换第2个/最后一个匹配项,如果只有一个匹配项,则使用该匹配项。

回调函数在使用回调的函数外部。

我认为我需要一个数组计数 - 减去一个 - 然后将该数字传递给回调函数并在那里使用它,但也许有更简单的方法吗?

简化的功能是:

function repWords($content) {
    foreach ($words_array as $w) {
        $content = preg_replace_callback('/\b('.$w.'[s]?)\b/S', array(&$this,'addHtml'), $content);
    }

    return $content;
}

function addHtml($format){
   return '<span>' . $format[1] . '</span>'
}

这可以根据需要替换它找到的所有单词,我可以将其设置为随机替换一些,但我想 替换 nth 发生和/或仅替换一个事件(并不总是第一次出现)。

1 个答案:

答案 0 :(得分:1)

根据您的要求,我想出了以下内容:

// needs to be global given that you are using non-anonymous function syntax
$count = 0;

function repWords($content) {
  global $count;

  $words_array = array('some','content','foobar');

  foreach ($words_array as $w) {
    $pattern = '~\b('.$w.'s?)\b~';
    $count=0;
    preg_match_all($pattern,$content,$matches);
    $count=count($matches[0]);
    if ($count>0)
      $content = preg_replace_callback($pattern,'addHtml',$content);
  }
  return $content;
}

function addHtml ($format) {
  global $count;
  static $cc=1;
  static $pf='';

  $val=$format[1];
  $cc = ($pf!=$val) ? 1 : ++$cc;

  if ((1==$count)||($cc==($count-1)))
    $format[1]= '<span>' . $val . '</span>';

  $pf=$val;
  return $format[1];
}


$content = <<<EOC
this is some content 
some more content
this content foobar
EOC;

echo repWords($content);

<强>输出

this is <span>some</span> content 
some more <span>content</span>
this content <span>foobar</span>
  • 第一个“some”被包装,因为它有2个实例
  • 第二个“内容”被包装,因为它有3个实例
  • “foobar”被包装,因为它只有一个实例

注意:这会使用全局变量$count。一般来说,使用全局变量是个坏主意。但是,当您选择单独定义回调而不是使用匿名函数时,由于php和preg_replace_callback(或任何可以指定回调的函数)的限制,这是少数几个被勉强接受的示例之一。如果您使用的是php5.3 +并且愿意使addHtml成为匿名函数,则可以使用$countuse传递给匿名函数。或者,如果所有这些实际上都在一个类中,则将其设为类属性并使用$this->count代替。

另一个注意事项:你说的最后一件事是“(并非总是第一次出现)”我对此感到有些困惑并认为可能意味着你想以某种方式指明 nth *而不是它始终是“倒数第二个(或者如果只有1个则是第一个”,例如在我的代码示例中,您可能希望将其更改为每个第3个到第3个字而不是第2个到最后一个字我请你澄清,但是当我发布这个解决方案时你没有回复,所以我没有编写代码以便灵活处理。但是,希望你能够采取这个并改变它以适合你这就是你想要的。基本上它将涉及将另一个arg传递给repWords,它还将涉及使用另一个全局变量在addHtml中使用,其中使用$cc==($count-1)