Как увеличить счетчик в строке замены при использовании preg_replace? - PullRequest
10 голосов
/ 02 февраля 2010

У меня есть этот код:

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

За каждую замену я получаю test0.

Я хотел бы получить test0, test1, test2 и т. Д.

Ответы [ 6 ]

15 голосов
/ 02 февраля 2010

Использование preg_replace_callback():

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

function rep_count($matches) {
  global $count;
  return 'test' . $count++;
}
6 голосов
/ 02 февраля 2010

Использование 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 - сложное и быстрое решение, но оно создает некоторые проблемы, поэтому я не рекомендую его.

4 голосов
/ 03 апреля 2014

После выхода PHP5.3 теперь мы можем использовать замыкание и ключевое слово use, чтобы обойти проблему global, поднятую Эмилем выше:

<code>    $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
";

Что возвращает:

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

Обратите внимание на use (&$count), следующий за именем функции - это позволяет нам читать $count в области действия функции (& делает ее переданной по ссылке и, следовательно, доступной для записи из области функции).

3 голосов
/ 17 декабря 2015

Также, если вы хотите избежать использования global:

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

1 голос
/ 28 июля 2017

Вам нужно только определить статическую переменную в функции обратного вызова:

$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;
1 голос
/ 02 февраля 2010

preg_replace_callback() позволит вам поработать над матчем, прежде чем вернуть его для последующей замены.

...