当字符串变量以数字开头时无法替换标记中的值
Having trouble replacing a value in a tag when a string variable starts with digit
我有一些代码,如果 $subtitle1
的值仅包含字母或 spaces,则正则表达式替换工作正常。当 $subtitle1
字符串以数字开头(例如“第 3 版”)时,preg_replace 函数会意外运行。如果我在替换字符串中添加一个 space,那么 $subtitle1 的值可以以数字开头并且没问题,但是它在“第 3 版”中的 3 之前放置了一个不需要的 space。
$raw_xml = '<property name="subtitle1" type="String">Linux is more than a shell</property>';
$subtitle1 = '3rd Edition';
$replacers = array (
'/(<property name="subtitle1" type="String">)([1-9A-Za-z ]+)(<\/property>)/' => sprintf("%s",$subtitle1), //1
'/(<property name="subtitle1" type="String">)([1-9A-Za-z ]+)(<\/property>)/' => sprintf(" %s",$subtitle1), //2
'/(<property name="subtitle1" type="String">)([1-9A-Za-z ]+)(<\/property>)/' => sprintf("%s",$subtitle1), //3
);
echo preg_replace(array_keys($replacers), array_values($replacers), $raw_xml);
//1 (when $subtitle1 = 'Third Edition', outputs: <property name="subtitle1" type="String">Third Edition</property>)
//2 (when $subtitle1 = '3rd Edition', outputs: <property name="subtitle1" type="String"> 3rd Edition</property>)
//3 (when $subtitle1 = '3rd Edition', outputs: rd Edition</property>)
如果 $subtitle1
var 的类型始终是字符串,我是否可以做一些不同的事情来让它正常工作?我已经尝试过修饰符 s、U,但没有得到任何进一步的结果。感谢您对此的任何见解。
问题是因为:sprintf("%s",$subtitle1)
输出:rd Edition
。
我猜正则表达式引擎将其理解为第 13 个捕获组。
好消息是,我为您找到了解决方案。
替换:$subtitle1 = '3rd Edition'
;
作者:$subtitle1 = '>3rd Edition<';
并像这样从第一个和第三个捕获组中提取 <>。
$replacers = array (
'/(<property name="subtitle1" type="String")>([1-9A-Za-z ]+)<(\/property>)/' => sprintf("%s",$subtitle1), //1
'/(<property name="subtitle1" type="String")>([1-9A-Za-z ]+)<(\/property>)/' => sprintf(" %s",$subtitle1), //2
'/(<property name="subtitle1" type="String")>([1-9A-Za-z ]+)<(\/property>)/' => sprintf("%s",$subtitle1), //3
);
你可以在这里测试:http://sandbox.onlinephpfunctions.com/code/05bf9a209bdcd6622bf494dc7f4887660e7a93a0
在纯理论平面上,您的代码不起作用导致解析器在评估字符串之前搜索 backreferences </code> 和 <code>
作为变量通过 sprintf 或 pcre 正则表达式引擎。
因此,要使其正常工作,只需替换 sprintf
文字字符串部分:
sprintf("%s",$subtitle1) -> sprintf('%s',$subtitle1)
# Note the change of -> to clearly delimit the backreference
# and the use of single quote string '...' instead of "..."
# (inside double quotes any $ start an evaluation as variables of string beside)
但是为了获得可靠的解决方案避免使用正则表达式解析xml并使用像这样的专用(简单而强大的)解析器:
<?php
$xml = <<<XML
<properties> <!-- Added -->
<property name="subtitle1" type="String">Linux is more than a shell</property>
</properties>
XML;
$properties = new SimpleXMLElement($xml);
$properties->property[0] = '3rd Edition';
echo $properties->asXML(); //Only the first is changed
在 Official Docs 上查看更多信息。
我有一些代码,如果 $subtitle1
的值仅包含字母或 spaces,则正则表达式替换工作正常。当 $subtitle1
字符串以数字开头(例如“第 3 版”)时,preg_replace 函数会意外运行。如果我在替换字符串中添加一个 space,那么 $subtitle1 的值可以以数字开头并且没问题,但是它在“第 3 版”中的 3 之前放置了一个不需要的 space。
$raw_xml = '<property name="subtitle1" type="String">Linux is more than a shell</property>';
$subtitle1 = '3rd Edition';
$replacers = array (
'/(<property name="subtitle1" type="String">)([1-9A-Za-z ]+)(<\/property>)/' => sprintf("%s",$subtitle1), //1
'/(<property name="subtitle1" type="String">)([1-9A-Za-z ]+)(<\/property>)/' => sprintf(" %s",$subtitle1), //2
'/(<property name="subtitle1" type="String">)([1-9A-Za-z ]+)(<\/property>)/' => sprintf("%s",$subtitle1), //3
);
echo preg_replace(array_keys($replacers), array_values($replacers), $raw_xml);
//1 (when $subtitle1 = 'Third Edition', outputs: <property name="subtitle1" type="String">Third Edition</property>)
//2 (when $subtitle1 = '3rd Edition', outputs: <property name="subtitle1" type="String"> 3rd Edition</property>)
//3 (when $subtitle1 = '3rd Edition', outputs: rd Edition</property>)
如果 $subtitle1
var 的类型始终是字符串,我是否可以做一些不同的事情来让它正常工作?我已经尝试过修饰符 s、U,但没有得到任何进一步的结果。感谢您对此的任何见解。
问题是因为:sprintf("%s",$subtitle1)
输出:rd Edition
。
我猜正则表达式引擎将其理解为第 13 个捕获组。
好消息是,我为您找到了解决方案。
替换:$subtitle1 = '3rd Edition'
;
作者:$subtitle1 = '>3rd Edition<';
并像这样从第一个和第三个捕获组中提取 <>。
$replacers = array (
'/(<property name="subtitle1" type="String")>([1-9A-Za-z ]+)<(\/property>)/' => sprintf("%s",$subtitle1), //1
'/(<property name="subtitle1" type="String")>([1-9A-Za-z ]+)<(\/property>)/' => sprintf(" %s",$subtitle1), //2
'/(<property name="subtitle1" type="String")>([1-9A-Za-z ]+)<(\/property>)/' => sprintf("%s",$subtitle1), //3
);
你可以在这里测试:http://sandbox.onlinephpfunctions.com/code/05bf9a209bdcd6622bf494dc7f4887660e7a93a0
在纯理论平面上,您的代码不起作用导致解析器在评估字符串之前搜索 backreferences </code> 和 <code>
作为变量通过 sprintf 或 pcre 正则表达式引擎。
因此,要使其正常工作,只需替换 sprintf
文字字符串部分:
sprintf("%s",$subtitle1) -> sprintf('%s',$subtitle1)
# Note the change of -> to clearly delimit the backreference
# and the use of single quote string '...' instead of "..."
# (inside double quotes any $ start an evaluation as variables of string beside)
但是为了获得可靠的解决方案避免使用正则表达式解析xml并使用像这样的专用(简单而强大的)解析器:
<?php
$xml = <<<XML
<properties> <!-- Added -->
<property name="subtitle1" type="String">Linux is more than a shell</property>
</properties>
XML;
$properties = new SimpleXMLElement($xml);
$properties->property[0] = '3rd Edition';
echo $properties->asXML(); //Only the first is changed
在 Official Docs 上查看更多信息。