将preg_replace替换引用作为数组键进行访问

时间:2016-10-30 02:55:52

标签: php regex

我有一个关联数组$dic,我想用href中的相应字符串替换HTML字符串中的$dic链接。

这是我的代码:

$string = preg_replace("/<a href=\"(.*?)\">(.*?)<\/a>/s", "$2->{$dic["$1"]}", $string);

上述正则表达式无法正常工作。但是在这种形式下它起作用:

$string = preg_replace("/<a href=\"(.*?)\">(.*?)<\/a>/s", "$2->$1", $string);

我想将<a>代码存储为LinkText->LinkFromDic

1 个答案:

答案 0 :(得分:2)

complex expression "$1"中的{$dic["$1"]}被解释为文字字符串"$1",因为:

  • 复制表达式在 preg_replace替换之前处理 引用已应用;
  • $1在PHP中是无效的variable name
      

    有效的变量名称以字母或下划线开头,后跟任意数量的字母,数字或下划线。

很容易验证:

$dic = ['$1' => 'Dollar One'];
var_dump("{$dic["$1"]}");

输出

string(10) "Dollar One"

较旧的PHP版本支持e正则表达式修饰符,它允许将替换字符串作为PHP代码进行评估。但它在PHP 5.5.0中已被弃用,并从PHP 7.0.0开始删除。

但是,php_replace_callback功能足够灵活,可以解决问题:

$dic = ['/page/a' => 'Page A'];

$string = <<<'EOHTML'
<a href="/page/a">Link</a>
EOHTML;

$string = preg_replace_callback('/<a href\="(.*?)">(.*?)<\/a>/s',
  function ($matches) use ($dic) {
    $v = isset($dic[$matches[1]]) ? $dic[$matches[1]] : $matches[1];
  return count($matches == 3) ? "{$matches[2]}->$v" : $matches[0];
}, $string);

var_dump($string);

输出

string(12) "Link->Page A"