PHP正则表达式在引号外的括号中

时间:2017-01-25 17:41:20

标签: php regex

php我想用$替换{{ $here $their '$literal' }}中的$this->。 这意味着我希望得到结果{{ $this->here $this->their '$literal' }},但我得到的是:{{ $this->here $their '$literal' }}

这是我的代码:

<?php

    $str = '{{ $here $their "$literal" }}';
    $search = '{{(?:\'[^\']+\'|"[^"]+")(*SKIP)(*F)|\$([0-9a-zA-Z_]++)}}';
    $replace = '$this->$1';

    // result is {{ $hello $this->by "$literal" }}
    $result = preg_replace('/' . $search . '/U', $replace, $str);

?>

有没有人知道如何替换{{}}中未引用的多个匹配项?

3 个答案:

答案 0 :(得分:1)

匹配{{...}}中的preg_replace_callback个子字符串,然后在anonynous方法中使用preg_replace,并使用位调整的正则表达式:

$str = '{{ $here $their "$literal" }}';
echo preg_replace_callback('~{{.*?}}~s', function($m) {
    return preg_replace('~(?:\'[^\']+\'|"[^"]+")(*SKIP)(*F)|\$\b~', '$this->$0', $m[0]);
}, $str);

请参阅PHP demo

'~{{.*?}}~s'正则表达式会匹配{{的非重叠事件,任何0 +字符尽可能少,直到第一个}}preg_replace内的正则表达式有点复杂:

  • (?:\'[^\']+\'|"[^"]+")(*SKIP)(*F) - '后跟1 {+ 1}}以外的1个字符,然后是'(由于'),或\'[^\']+\'使用除"之外的1+个字符然后"(由于"),并且一旦该子字符串匹配,它就会被丢弃并且正则表达式引擎继续进行下一个匹配(由于"[^"]+"
  • (*SKIP)(*F) - 或
  • | - 一个\$\b符号后跟一个单词字符。

答案 1 :(得分:1)

如果你的字符串已经用双花括号括起来,你只需写下:

$pattern = '~[^"\'$]*+(?:"[^"]*"[^"\'$]*|\'[^\']*\'[^"\'$]*)*+\$\b\K~A';
$str = preg_replace($pattern, 'this->', $str);

但如果你的双花括号括号部分是一个较大的文字,而你不想替换大括号外的其他$var,你需要这个:

$pattern = '~(?:\G(?!\A)|{{)[^"\'$}]*+(?:"[^"]*"[^"\'$}]*|\'[^\']*\'[^"\'$}]*)*+\$\b\K~';

使用相同的替换字符串。

模式1详细信息:

此模式匹配所有字符,直到$(包含)。避免引用部分的最简单方法是在一美元之前匹配所有部分,并使用\K从匹配结果中删除所有部分。 A修饰符(类似于模式开头的\G)确保所有匹配都是连续的(没有间隙)。

~ # pattern delimiter
[^"'$]*+ #"# all characters except quotes and dollars
(?: # quoted parts
    "[^"]*" [^'"$]*  
  |
    '[^']*' [^"'$]*  
)*+
\$
\b  # no need to write `[a-zA-Z0-9_]+` and to capture it
    # after a literal "$" a word boundary suffices.
\K  # KEEP: characters before this token are removed from the match result
~A  # ANCHORED: force the matches to be contiguous from the start 
    # of the string until the last match. If one position fails, no
    # more match are possible

答案 2 :(得分:0)

您可能需要以下内容:

$str = '{{ $here $their "$literal" }}';
$result = preg_replace('/(\$.*?)\s(\$.*?)/i', '$this->$1 $this->$2', $str);

<强>样本
http://ideone.com/DO45Se