3

使用preg_replace_callback,是否可以只替换一个反向引用?还是我必须全部退回?

我只是想用引号包裹令牌的默认值。

$str = 'This is a {$token|token was empty}';
$str = preg_replace_callback('~{\$\w+\|(.*)?}~i', function($match) {
    //$match[1] is "token was empty"
    //I want to just replace $match[1], but it needs me to return the whole thing
}, $str);

我是否必须获取更多的反向引用,以便能够构建一个新版本的令牌并返回它,我不能只替换反向引用 1?谢谢。

4

3 回答 3

4

我是否必须获取更多的反向引用,以便能够构建一个新版本的令牌并返回它,我不能只替换反向引用 1?

你有两个选择:

  1. 如您所说,使用额外的反向引用来构造替换字符串,或者
  2. 使用环视仅匹配您要替换的部分。

通常我建议使用第一种方法,因为第二种方法效率较低,并且在某些情况下可能导致无效匹配(当前瞻和后向可能重叠时)。在这种情况下,不会有问题。

第二个选项的示例是:

preg_replace_callback('~{\$\w+\|\K(?:[^{}]+)?(?=})~i', function($match){
    // $match[0] contains what used to be the first capturing group.
    // return the value you want to replace it with
    // (you can still use the capturing group if you want, but it's unnecessary)
});
  • \K是一种从实际匹配中排除它之前的所有内容的方法(就像我们在那里有一个可变长度的lookbehind)。
  • (?=})是一个前瞻,表示以下必须是 a}但不将其包含在它自己的匹配中。
于 2012-08-14T22:08:14.477 回答
2

你会想使用这样的正则表达式,而不是:

~\{\$(\w+?)(?:\|(.+?))?\}~i

然后,您可以轻松查看传递给回调的内容:

$str = 'This is a {$token|token was empty}';
$str = preg_replace_callback('~\{\$(\w+?)(?:\|(.+?))?\}~i', function($match) {
    var_dump($match);
    exit;
}, $str);

输出:

array(3) {
  [0]=>
  string(24) "{$token|token was empty}"
  [1]=>
  string(5) "token"
  [2]=>
  string(15) "token was empty"
}

从那里,您可以检查是否$match[1]已设置,如果已设置,则返回其值,否则返回$match[2]

$foo = 'foo';
$str = 'Foo: {$foo|not set}, Bar: {$bar|not set}';
$str = preg_replace_callback('~\{\$(\w+?)(?:\|(.+?))?\}~i', function($match) {
    if (isset($GLOBALS[$match[1]])) {
        return $GLOBALS[$match[1]];
    } else {
        return $match[2];
    }
}, $str);
var_dump($str);

输出:

string(22) "Foo: foo, Bar: not set"

注意:我在$GLOBALS这里仅用于演示目的。如果可能的话,我建议使用 PHP 5.4 的闭包绑定,因为那时你可以为闭包分配一个特定的对象作为上下文(例如你的模板/视图对象或任何包含你试图替换的变量) . 如果你不使用 PHP 5.4,你也可以使用语法function($match) use ($obj)$obj你的上下文在哪里,然后检查isset($obj->{$match[1]})你的闭包。

于 2012-08-14T21:17:19.397 回答
0

我最近想出了一种更简单的方法来做到这一点。例如; 如果我想匹配\w+\d+\w+并且只更改数字。

$value = preg_replace_callback('~(\w+)(\d+)(\w+)~', function($match) {
    $match[2] = $match[2] * 2;//Do whatever I want to $match[2]
    return $match[1] . $match[2] . $match[3];
}, $value);

很干净!

于 2012-12-20T20:54:47.227 回答