我试图找到字符串中的所有PHP变量。
所有PHP变量都以$字符开头,所以我基本上在双引号字符串中搜索该字符。
我希望我的正则表达式适用于多行的字符串。 到目前为止,我有这个:
"[^"]*?\$[\w\d]+[^"]*?"
然而,在这种情况下说:
"a string" with no $variable in it
"a single line string with a $variable in it"
在第一行,匹配$ variables结尾的最后一个引号。显然,如果正则表达式只应在引号内搜索此字符。
任何帮助将不胜感激。 感谢
答案 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在他的回答中谈到的所有内容(通常,正确的决定是倾听他)。
根据您想要做的范围,它可能仍然适用,但要正确使用它,您必须了解其局限性。
...现在我看到你已经在评论中讨论了所有这些,希望这篇文章能让事情更清楚:)