正则表达式在字符串中查找PHP变量

时间:2014-04-20 13:03:14

标签: php regex sublimetext

我试图找到字符串中的所有PHP变量。

所有PHP变量都以$字符开头,所以我基本上在双引号字符串中搜索该字符。

我希望我的正则表达式适用于多行的字符串。 到目前为止,我有这个:

"[^"]*?\$[\w\d]+[^"]*?"

然而,在这种情况下说:

"a string" with no $variable in it

"a single line string with a $variable in it"

在第一行,匹配$ variables结尾的最后一个引号。显然,如果正则表达式只应在引号内搜索此字符。

任何帮助将不胜感激。 感谢

2 个答案:

答案 0 :(得分:3)

一种简单的方法是使用tokenizer

$source = <<<'EOD'
<?php // <-- needed
$data = 'Sed pulvinar metus $eget';
echo "tellus euismod tristique. $Nullam vitae";
if ($data === "mi id risus {$pretium['porttitor']} $vitae a lorem.")
// Aenean laoreet $urna eu erat laoreet, sit amet pretium purus consequat.
/* print "Curabitur $iaculis augue eget arcu dapibus"; */
echo <<<DATA
Duis id $mauris at ante ornare eleifend at sed magna
DATA;
EOD;

$tokens = token_get_all($source);
$flag = false;
$result = array();

foreach ($tokens as $token) {
    if ($token =='"')
        $flag = ! $flag;
    elseif ($flag && is_array($token) && $token[0] == T_VARIABLE)
        $result[] = $token[1]; 
}
print_r($result);

事实上,它也可以用正则表达式模式完成。但是,模式会比你想象的更复杂,因为你需要跳过:注释,简单引号中的字符串,heredoc,nowdoc,双引号内部没有变量的字符串。为了给你一个想法,请查看关于php评论的this post

注意:您可以轻松更改此代码以处理heredoc语法(或任何您想要的)

答案 1 :(得分:1)

为什么你的正则表达式失败

考虑在字符串

上应用"[^"]*?\$[^"]*"时发生的情况
"a string" with no $variable in it "here's $foobar"

您要做的是选择$foobar。但正则表达式引擎从左向右移动,因此首先它会尝试匹配"a string"[^"]阻止超出引号)。

不工作,没有问题,因为正则表达式没有锚定传输开始,我们尝试从第二个引用:" with no $variable in it "。这匹配,因此返回。

由于匹配“吃”了第三个引号,我们与here's $foobar"不匹配。您最终选择的是$variable而不是$foobar

解决(天真)问题

为了避免这种行为,我们需要匹配不包含变量的带引号的字符串。这样,只有连贯的“卷轴”字符串才被视为正则表达式的潜在匹配。

您可以使用

("[^"]*?\$[\w\d]+[^"]*")|("[^"]*")

带引号的变量引用字符串将在第一组中捕获,其他字符串在第二组中捕获;见here for an example

<强>声明

这是一个快速的解决方案,并没有考虑逃脱的引用,评论以及Casimir et Hippolyte在他的回答中谈到的所有内容(通常,正确的决定是倾听他)。

根据您想要做的范围,它可能仍然适用,但要正确使用它,您必须了解其局限性。

...现在我看到你已经在评论中讨论了所有这些,希望这篇文章能让事情更清楚:)