2014-03-28 37 views
0

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

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

我想我需要一个数组 - 减一 - 然后将该数字传递给回调函数并在那里使用它,但也许有更简单的方法来做到这一点?

简化的功能是:

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个发生和/或仅替换一个发生(并不总是第一次出现)。

+0

最后一段引发我的兴趣,似乎没有与你以前的陈述jive。你可以给一个实际的“之前”和“之后”的例子? –

+0

所以你不希望这个方法是正确的:在数组中找到所有匹配的单词,将'count-1'传递给回调函数? – mesutozer

+0

也,你使用什么版本的PHP –

回答

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> 
  • 第一 “一些” 是包裹,因为有2个实例其中
  • 第二个“内容”被封装,因为有3个实例它
  • “foobar的”包裹,因为只有1它

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

另注:你说的是“(并不总是第一个出现)”我是有点这种困惑,把它可能意味着你想以某种方式能够指定第n个的最后一步*而不是总是“倒数第二(或第一,如果只有1”,例如在我的代码示例中,也许你想将它改为倒数第二个字,而不是第二个倒数第二个字)我请求你澄清,但你没有在我发布这个解决方案的时候没有回应,所以我没有写代码来灵活处理,但是,如果这是你想要的,希望你能够接受并修改它以适应你。基本上,它将涉及将另一个参数传递到repWords,并且还将涉及使用另一个全局变量用于addHtml,其中使用$cc==($count-1)

+0

感谢您的答案! ...我还没有申请这个,但会尝试一下,看看它是如何工作的。在“不是第一次出现”的部分,我真正想要做的是抛出一个随机选择,并限制它只换出n个可能选项中的一个,但理想情况下也不是第一个选项(如果有时尽管抓住第一个选项)。 ...我会修补并让你知道它是怎么回事。 – gtr1971

+0

好的,我已经能够插入你的解决方案,并且我得到了不同的结果。如果一个单词出现在内容中3次,代码将操纵最后两个事件,而不是第二个事件。我在这里要做的一件事情是限制HTML替换的数量(在这种情况下,它是页面锚点)。我想限制内容中锚点的总数不超过3个最大值。 – gtr1971

+0

感谢您的解决方案!我做了一些调整和修改以满足其他一些要求,但是让我有了很长的路要走。 – gtr1971