RegEx匹配变量或字符串的值(带或不带引号)

时间:2013-12-28 08:11:57

标签: php regex string variables

这是我的困境:

我写了这个RegEx模式,它在我的沙箱中有效但在我的网站上不起作用:

沙箱:http://regex101.com/r/vP3uG4

模式:

(.*[$]'.$variable.'\s*=\s*\'?)(.*?)(\'?;.*)

代码行如下:

$savedsettings_new = preg_replace('/(.*[$]'.$variable.'\s*=\s*\'?)(.*?)(\'?;.*)/is','$1'. $value .'$3',$savedsettings_temp);

正如您所看到的,它可以在沙盒上运行,但它不能正常工作。

我试图匹配可以表示为字符串的变量值(带有单引号)或没有引号的数值,如下所示:

$match_string = 'value';
$match_number = 1;

现在这个代码可以正常使用字符串,但是数字变量没有包含在字符串中我只是获得后向引用$ 3的内容而且之前我什么都没得到!

我正在摸不着头脑,真的无法弄清楚为什么它在RegEx101上工作但不能正常工作......当我匹配一个或没有单引号时,我不是做正确的事情(并且因为preg_replace而逃避它们有报价?

2 个答案:

答案 0 :(得分:2)

好的,发现了这个问题。解决方案是将反向引用包装在${}

引用PHP manual

  

当使用替换模式时,后向引号后面紧跟另一个数字(即:在匹配的模式后立即放置一个文字数字),您不能使用熟悉的\\1表示法进行反向引用。例如,\\11会混淆preg_replace(),因为它不知道您是否希望\\1反向引用后跟文字1,或\\11反向引用后跟无效。在这种情况下解决方案是使用\${1}1

因此,您的代码应如下所示:

header('Content-Type: text/plain');

$variable = 'tbs_development';
$value = '333';

$savedsettings_temp = <<<'CODE'
$tbs_underconstruction = 'foo';
$tbs_development = 0;
CODE;

$pattern = '/(.*[$]'.preg_quote($variable).'\s*=\s*\'?)(.*?)(\'?;.*)/is';
$replacement = '${1}'.$value.'${3}';

$savedsettings_new = preg_replace($pattern, $replacement, $savedsettings_temp);

echo $savedsettings_new;

输出:

$tbs_underconstruction = 'foo';
$tbs_development = 333;

Demo.

答案 1 :(得分:1)

如果变量$value包含数值,那么preg_replace中的替换模式将如下所示:$12$3

这是真的但不像你预期的那样。在Regex Engine中,$ddd或此处$dd(等于\ddd\dd)被视为八进制数。

因此,在这种情况下,$12表示八进制索引12,它等于ASCII中的一种空格。

如果在正则表达式中处理这些棘手的问题,您应该将您的反引用号码包含在{}内,这样它应该是${1}2${3}

将替换模式更改为'${1}'.$value.'${3}'