在php中简单的增量字符串替换

时间:2011-09-07 07:50:54

标签: php string replace preg-replace

我有以下代码:

<?php
$subject = "Replace ? question mark in brackets [? with ? incremental ??]? digits";
echo incremental_replace($subject);
// i want the folowing: 
// Replace ? question mark in brackets [1 with 2 incremental 34]? digits

我希望替换括号中的所有?。此外,?的数量和位置可能会发生变化。

我如何用PHP做到这一点?我认为这可以用preg_replace完成,但我不知道如何。

5 个答案:

答案 0 :(得分:3)

如果括号没有嵌套,那么以下就足够了

echo preg_replace('~\?(?=[^\[\]]*\])~e', '++$n', $subject);

否则使用解析器:

$subject = "Replace ? question mark in [nested ? brackets] [? with ? [incremental ? [?]] ??]? digits";
$result = '';

$bc = $n = 0;
foreach(str_split($subject) as $c) {
    if($c == '[') $bc++;
    if($c == ']') $bc--;
    if($c == '?' && $bc) $c = ++$n;
    $result .= $c;
}

echo $result;

嵌套括号的正则表达式是可能的,但是会太长并且搞砸了。


OP注意:如果替换不是增量数字而是数组,您可以执行以下操作:

$n = 0;
$rep = array('foo', 'bar', 'baz', 'qux', 'quux');
echo preg_replace('~\?(?=[^\[\]]*\])~e', '$rep[$n++]', $subject);

答案 1 :(得分:2)

正确解决问题

function incremental_replace($subject) {
    $replacer = function($matches) {
        $index = 0;
        return preg_replace('/\?/e', '++$index', $matches[0]);
    };
    return preg_replace_callback('/\[[^\]]*\]/', $replacer, $subject);
}

$subject = "Replace ? question mark in brackets [? with ? incre?mental ??]?...";
echo incremental_replace($subject);

此答案的上一种形式

我误解了这个问题,并回答了另一个类似的问题。我在这里留下答案,因为有人可能觉得它很有用。

一般的想法是:

function replacer($matches) {
    $replacements = array(1, 2, 34);
    $index = 0;
    return preg_replace('/\?+/e', '$replacements[$index++]', $matches[0]);
}

$subject = "Replace ? question mark in brackets [? with ? incremental ??]?...";
echo preg_replace_callback('/\[[^\]]*\]/', 'replacer', $subject);

<强> See the basic concept in action

如果你使用PHP&gt; = 5.3,那么你可以做一个更通用的解决方案:

function incremental_replace($subject, $replacements) {
    $replacer = function($matches) use ($replacements) {
        $index = 0;
        return preg_replace('/\?+/e', '$replacements[$index++]', $matches[0]);
    };
    return preg_replace_callback('/\[[^\]]*\]/', $replacer, $subject);
}


$subject = "Replace ? question mark in brackets [? with ? incremental ??]?...";
echo incremental_replace($subject, array(1, 2, 34));

最后,如果您愿意将自己限制在仅限单个问号(即如果括号内的??可以更改为?),那么您可以将“替换器”功能中的preg_replace与简单的str_replace交换,这样会更快。

答案 2 :(得分:1)

一个简单的解析器可以完成这项工作。这只是一个简单的解决方案,有改进的余地。但在这种情况下,preg_replace()preg_replace_callback()可能更有效。

function incremental_replace($subject) {
    $inBracket  = 0;
    $length = strlen($subject);
    $count      = 0;
    $result = '';
    for ($i = 0; $i < $length; $i++) {
        $char = $subject[$i];
        switch ($char) {
            case '[':
                $inBracket++;
                break;
            case ']':
                $inBracket--;
                break;
            case '?':
                if ($inBracket > 0) {
                    $char = ++$count;
                }
                break;
        }
        $result .= $char;
    }
    return $result;
}

$subject = "Replace ? question mark in brackets [? with ? incremental ??]? digits";
echo incremental_replace($subject);
// Replace ? question mark in brackets [1 with 2 incremental 34]? digits

答案 3 :(得分:1)

function replaceThem($matches){
    $i = 1;
    while ($pos = strpos($matches[0], '?'))
        $matches[0][$pos] = $i++;
    return $matches[0];
}
$subject = "Replace ? question mark in brackets [? with ? incremental ??]? digits";
echo preg_replace_callback('/\[[^\]]+\]/', 'replaceThem', $subject);

http://www.ideone.com/kBnMK

答案 4 :(得分:0)

也许最好循环遍历字符串的字符。如果您通过开口支架,请将您遇到的问号替换为计数器,同样替换第二个等问题,如果您通过了关闭支架......请停止更换。