Here is my dilemma:
这是我的困境:
I wrote this RegEx pattern which works in my sandbox but does not work on my website:
我写了这个RegEx模式,它可以在我的沙箱中工作,但是不能在我的网站上工作:
Sandbox: http://regex101.com/r/vP3uG4
沙盒:http://regex101.com/r/vP3uG4
Pattern:
模式:
(.*[$]'.$variable.'\s*=\s*\'?)(.*?)(\'?;.*)
The line of code goes like this:
代码行是这样的:
$savedsettings_new = preg_replace('/(.*[$]'.$variable.'\s*=\s*\'?)(.*?)(\'?;.*)/is','$1'. $value .'$3',$savedsettings_temp);
As you can see it works on the sandbox but it doesn't work live.
正如你所看到的,它在沙箱上工作,但在现场却不工作。
I am trying to match values of variables that can be expressed as strings (with single quotes around them) or numerical values with no quotes, like so:
我正在尝试匹配可以用字符串(带单引号)表示的变量的值或不带引号的数值,如下所示:
$match_string = 'value';
$match_number = 1;
Right now this code works fine with strings but with numerical variables that are not enclosed in strings I just get the contents of the backreference $3 and I don't get anything at all before that!
现在,这个代码可以用字符串处理,但是对于不包含在字符串中的数值变量,我只需要得到backreference $3的内容,在此之前我什么也得不到!
I'm scratching my head and really can't figure out why it works on RegEx101 but not live... Aren't I doing the right thing when matching for one or no single quotes (and escaping them because the preg_replace has quotes?
我在挠头,真的搞不懂为什么它能在RegEx101上运行,但却无法生存……当匹配一个或没有单引号时,我做的不是正确的吗(并转义它们,因为preg_replace有引号)?
2 个解决方案
#1
2
Okay, found out the issue. The solution is to wrap the backreference in ${}
.
好吧,发现问题了。解决方案是用${}来包装反向引用。
Quoting the PHP manual:
引用PHP手册:
When working with a replacement pattern where a backreference is immediately followed by another number (i.e.: placing a literal number immediately after a matched pattern), you cannot use the familiar
\\1
notation for your backreference.\\11
, for example, would confuse preg_replace() since it does not know whether you want the\\1
backreference followed by a literal1
, or the\\11
backreference followed by nothing. In this case the solution is to use\${1}1
.当使用替换模式时,在该模式中,一个反向引用紧接着另一个数字(即:在匹配的模式之后立即放置一个文字数字),不能使用熟悉的\1符号来进行反向引用。举个例子,\11会混淆preg_replace(),因为它不知道您是想要一个后跟文字1的\1的backreference,还是什么都不想要的\11的backreference。在这种情况下,解决方案是使用\${1}1。
So, your code should look like:
因此,您的代码应该如下所示:
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;
Output:
输出:
$tbs_underconstruction = 'foo';
$tbs_development = 333;
演示。
#2
1
If the variable $value
contains a numerical value then the replacement pattern in your preg_replace
will look like this: $12$3
如果变量$value包含一个数值,那么preg_replace中的替换模式将如下所示:$12$3
That's true but not as you expected. In Regex Engine, $ddd
or here $dd
(which are equal to \ddd
and \dd
) are treated as octal numbers.
这是真的,但不是你想的那样。在Regex引擎中,$ddd或这里的$dd(等于\ddd和\dd)被视为八进制数。
So in this case $12
means a octal index 12 which is equal to a kind of space in ASCII.
在这种情况下,$12表示八进制索引12它等于ASCII的一种空间。
In the case of working with these tricky issues in Regular Expressions you should wrap your backreference number within {}
so it should be ${1}2${3}
对于在正则表达式中处理这些棘手问题的情况,您应该在{}中将您的backreference编号包装为${1}2${3}
Change your replacement pattern to '${1}'.$value.'${3}'
将替换模式更改为${1}.$value. ${3}
#1
2
Okay, found out the issue. The solution is to wrap the backreference in ${}
.
好吧,发现问题了。解决方案是用${}来包装反向引用。
Quoting the PHP manual:
引用PHP手册:
When working with a replacement pattern where a backreference is immediately followed by another number (i.e.: placing a literal number immediately after a matched pattern), you cannot use the familiar
\\1
notation for your backreference.\\11
, for example, would confuse preg_replace() since it does not know whether you want the\\1
backreference followed by a literal1
, or the\\11
backreference followed by nothing. In this case the solution is to use\${1}1
.当使用替换模式时,在该模式中,一个反向引用紧接着另一个数字(即:在匹配的模式之后立即放置一个文字数字),不能使用熟悉的\1符号来进行反向引用。举个例子,\11会混淆preg_replace(),因为它不知道您是想要一个后跟文字1的\1的backreference,还是什么都不想要的\11的backreference。在这种情况下,解决方案是使用\${1}1。
So, your code should look like:
因此,您的代码应该如下所示:
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;
Output:
输出:
$tbs_underconstruction = 'foo';
$tbs_development = 333;
演示。
#2
1
If the variable $value
contains a numerical value then the replacement pattern in your preg_replace
will look like this: $12$3
如果变量$value包含一个数值,那么preg_replace中的替换模式将如下所示:$12$3
That's true but not as you expected. In Regex Engine, $ddd
or here $dd
(which are equal to \ddd
and \dd
) are treated as octal numbers.
这是真的,但不是你想的那样。在Regex引擎中,$ddd或这里的$dd(等于\ddd和\dd)被视为八进制数。
So in this case $12
means a octal index 12 which is equal to a kind of space in ASCII.
在这种情况下,$12表示八进制索引12它等于ASCII的一种空间。
In the case of working with these tricky issues in Regular Expressions you should wrap your backreference number within {}
so it should be ${1}2${3}
对于在正则表达式中处理这些棘手问题的情况,您应该在{}中将您的backreference编号包装为${1}2${3}
Change your replacement pattern to '${1}'.$value.'${3}'
将替换模式更改为${1}.$value. ${3}