我有以下文字:
$string='
blah<br>
@include (''file_to_load'')
<br>
@include (''file_to_load'',''param1'',''param2'',''param3'')
';
我想用参数捕获(然后使用 preg_replace_callback 替换)"@include"的所有出现(例如@include('file_to_load'、'param1'、'param2'、'param3')
所以我这样做:
$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() 函数爆炸后,它显然不像我想要的那样工作。
我有一种方法可以通过逗号爆炸()(可能使用正则表达式)字符串,但当逗号在撇号内时则不行?
使用以下命令进行拆分:
,(?=([^']*'[^']*')*[^']*$)
使用preg_split
,因为explode
不支持正则表达式:
法典:
$params = preg_split(',(?=([^']*'[^']*')*[^']*$)',$matches[1]);
你要找的是标记化。不要试图在逗号上拆分。相反,请标识表达式的每个构建基块。所以你需要匹配,而不是分裂。
例如,这个简单的正则表达式:
'[^']+'
将匹配以下元素:
@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'
'(?:[^']++|'')*'
尝试使用这个:
"'@include['s]*'([^')]*')"
这将匹配
@include (''file_to_load'')
和
@include (''file_to_load'',''param1,something'',[''elem''=>''also, a comma'']])
我希望这有所帮助。