我有以下文字:
$string='
blah<br>
@include (\'file_to_load\')
<br>
@include (\'file_to_load\',\'param1\',\'param2\',\'param3\')
';
我想用参数(例如@include('file_to_load','param1','param2','param3'))来捕获(然后使用preg_replace_callback替换)所有出现的“@include”)
所以我这样做:
$string='
blah<br>
@include (\'file_to_load\')
<br>
@include (\'file_to_load\',\'param1\',\'param2\')
';
$params=[];
$result = preg_replace_callback(
'~@include \((,?.*?)\)~',//I catch @include, parenthesis and all between them
function ($matches) {
echo '---iteration---';
$params=explode(',',$matches[1]);//exploding by a comma
echo '<pre>';
var_dump($params);
echo '</pre>';
return $matches[1];
},
$string
);
一切都很好,直到逗号出现在里面一个参数,就像这里一样:
$string='
blah<br>
@include (\'file_to_load\')
<br>
@include (\'file_to_load\',\'param1,something\',[\'elem\'=>\'also, a comma\']])
';
这里我们在“param1”参数中有一个逗号,现在,在使用explode()函数爆炸后,它显然不能像我想的那样工作。
我有一种方法可以使用逗号来爆炸()(通过使用正则表达式)字符串,但是当逗号位于撇号内时不能吗?
答案 0 :(得分:2)
使用以下内容进行拆分:
,(?=([^']*'[^']*')*[^']*$)
使用preg_split
,因为explode
不支持正则表达式:
<强>代码:强>
$params = preg_split(',(?=([^']*'[^']*')*[^']*$)',$matches[1]);
答案 1 :(得分:2)
您正在寻找的是标记化。不要试图分裂逗号。而是识别表达式的每个构建块。所以你需要匹配,而不是拆分。
例如,这个简单的正则表达式:
'[^']+'
将匹配这些元素:
@include ('file_to_load','param1,something',['elem'=>'also, a comma'])
\____________/ \________________/ \____/ \_____________/
但是对于你的情况可能还不够,因为你有一个数组,我想你也必须解析它。
分别识别每个参数:
'[^']+'|\[.+?\]
@include ('file_to_load','param1,something',['elem'=>'also, a comma'])
\____________/ \________________/ \_______________________/
这种方法的问题在于它不允许您匹配嵌套数组。如果您需要能够解析它,那么模式会变得更复杂:
(?(DEFINE)
(?<string>'[^']+')
(?<array> \[ (?: (?&arrayitem) (?> , \s* (?&arrayitem) )* )? \] )
(?<arrayitem> \s* (?&string) \s* => \s* (?&value) \s* )
(?<value> (?&string) | (?&array) )
)
(?&value)
是的,这是一个递归的正则表达式,但它实际上可以识别参数:
@include ('file_to_load','param1,something',['elem'=>'also, a comma','other'=>['nested' => 'array']])
\___________/ \________________/ \______________________________________________________/
由于我不知道您之后要对参数做什么,实际上您可能需要编写解析器而不是使用正则表达式,但这取决于您将要做什么分割参数后尝试做。
旁注:如果您希望能够在字符串中转义引号,则可能需要将'[^']+'
字符串模式替换为更复杂的内容。
有两种广泛接受的方法可以做到这一点:
使用反斜杠:'abc\'def'
'(?:[^\\']++|\\.)*'
报价加倍:'abc''def'
'(?:[^']++|'')*'
答案 2 :(得分:0)
尝试使用:
"\@include[\s]*\([^\)]*\)"
这将匹配
@include (\'file_to_load\')
和
@include (\'file_to_load\',\'param1,something\',[\'elem\'=>\'also, a comma\']])
我希望这会有所帮助。