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

时间:2022-08-09 18:02:27

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 literal 1, 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;

Demo.

演示。

#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 literal 1, 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;

Demo.

演示。

#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}