使用preg_replace时如何增加替换字符串中的计数?

时间:2010-02-02 14:14:24

标签: php regex string preg-replace

我有这段代码:

$count = 0;    
preg_replace('/test/', 'test'. $count, $content,-1,$count);

对于每次替换,我都获得test0。

我想获得test0,test1,test2等。

6 个答案:

答案 0 :(得分:15)

使用preg_replace_callback()

$count = 0;
preg_replace_callback('/test/', 'rep_count', $content);

function rep_count($matches) {
  global $count;
  return 'test' . $count++;
}

答案 1 :(得分:6)

使用preg_replace_callback()

class TestReplace {
    protected $_count = 0;

    public function replace($pattern, $text) {
        $this->_count = 0;
        return preg_replace_callback($pattern, array($this, '_callback'), $text);
    }

    public function _callback($matches) {
        return 'test' . $this->_count++;
    }
}

$replacer = new TestReplace();
$replacer->replace('/test/', 'test test test'); // 'test0 test1 test2'

注意:使用global是一种难以解决的解决方案,但它会引入一些问题,所以我不推荐它。

答案 2 :(得分:4)

在PHP5.3发布之后,我们现在可以使用闭包和use关键字来解决Emil上面提出的global问题:

    $text = "item1,\nitem2,\nFINDME:23623,\nfoo1,\nfoo2,\nfoo3,\nFINDME:923653245,\nbar1,\nbar2,\nFINDME:43572342,\nbar3,\nbar4";
$pattern = '/FINDME:(\d+)/';
$count = 1;
$text = preg_replace_callback(  $pattern
                            ,   function($match) use (&$count) {
                                    $str = "Found match $count: {$match[1]}!";
                                    $count++;
                                    return $str;
                                }
                            ,   $text
                            );
echo "<pre>$text</pre>";

返回:

item1,
item2,
Found match 1: 23623!,
foo1,
foo2,
foo3,
Found match 2: 923653245!,
bar1,
bar2,
Found match 3: 43572342!,
bar3,
bar4

注意函数名后面的use (&$count) - 这允许我们在函数范围内读取$count(&amp;使其通过引用传递,因此可以从函数的范围写入)

答案 3 :(得分:3)

另外,如果您想避免使用global:

$count = 0; preg_replace_callback('/test/', function rep_count($matches) use (&$count) { return 'test' . $count++; }, $content);

答案 4 :(得分:1)

preg_replace_callback()将允许您在返回之前对匹配进行操作,以便后续替换。

答案 5 :(得分:1)

您只需在回调函数中定义一个静态变量:

$result = preg_replace_callback('/test/', function ($m) {
    static $count = 0;
    return 'test' . $count++;
}, $content);

这样就不会污染全局命名空间。

对于这种特殊情况,您还可以使用简单的功能:

$parts = explode('test', $content);
$end = array_pop($parts);
$result = '';

foreach($parts as $k=>$v) {
    $result .= 'test' . $k;
}

$result .= $end;