【问题标题】:Need to count matches and replace "nth" match using preg_replace_callback需要计算匹配并使用 preg_replace_callback 替换“第 n 个”匹配
【发布时间】:2014-05-08 13:09:14
【问题描述】:

我需要搜索一些内容并用 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>'
}

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

【问题讨论】:

  • 最后一段有点让我失望,似乎与您之前的陈述不符..您能给出一个实际的“之前”和“之后”的例子吗?
  • 所以你不希望这个方法正确:查找数组中的所有单词匹配,将count-1传递给回调函数?
  • 还有,你用的是什么版本的php

标签: php regex replace preg-replace-callback


【解决方案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”被包装,因为它只有 1 个实例

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

另一个注意事项:你说的最后一句话是“(并不总是第一次出现)”我对此有些困惑,并认为它可能意味着你希望能够以某种方式指定nth* 而不是它总是“倒数第二个”(或者如果只有 1 个则为第一个),例如在我的代码示例中,也许您想将其更改为倒数第三个单词而不是倒数第二个单词。我要求你澄清,但在我发布这个解决方案时你没有回复,所以我没有编写代码来灵活地解决这个问题。但是,如果你应该能够接受并改变它以适应你这就是你想要的。基本上它将涉及将另一个 arg 传递给 repWords,它还将涉及在 addHtml 中使用另一个全局变量,其中使用了 $cc==($count-1)

【讨论】:

  • 感谢您的回答! ...我还没有应用这个,但会尝试一下,看看它是如何工作的。对于“不是第一次出现”部分,我真正想做的是随机选择并将其限制为仅交换“n”个可能选项中的一个,但理想情况下也不是第一个选项(如果有时它没有什么大不了的虽然抓住了第一个选项)。 ...我会修修补补,让你知道它是怎么回事。
  • 好的,我已经能够插入您的解决方案,但结果好坏参半。如果一个单词在内容中出现 3 次,则代码正在处理最后两次出现而不是倒数第二次。我在这里尝试做的一件事也是限制 HTML 替换的数量(在本例中是页面锚点)。我想将内容中的锚点总数限制为最多不超过 3 个。
  • 感谢您的解决方案!我进行了一些调整和修改以满足其他一些要求,但这让我在解决问题方面取得了长足的进步。
猜你喜欢
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 2012-03-07
  • 2021-01-26
  • 2012-09-19
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
相关资源
最近更新 更多