我正在尝试使用preg_match提取表达式的一部分。
我有以下字符串
${classA.methodA.methodB(classB.methodC(classB.methodD)))}
,需要完成两件事:a.验证语法
${classA.methodA.methodB(classB.methodC(classB.methodD)))}
有效${classA.methodA.methodB}
有效${classA.methodA.methodB()}
无效${methodB(methodC(classB.methodD)))}
无效
b. 我需要提取这些信息
${classA.methodA.methodB(classB.methodC(classB.methodD)))}
应该返回
1. classA
2. methodA
3. methodB(classB.methodC(classB.methodD)))
我已经创建了以下代码
$expression = '${myvalue.fdsfs.fsdf.blo(fsdf.fsfds(fsfs.fs))}';
$pattern = '/\$\{(?:([a-zA-Z0-9]+)\.)(?:([a-zA-Z\d]+)\.)*([a-zA-Z\d.()]+)\}/';
if(preg_match($pattern, $expression, $matches))
{
echo 'found'.'<br/>';
for($i = 0; $i < count($matches); $i++)
echo $i." ".$matches[$i].'<br/>';
}
结果是:
找到了
0 ${myvalue.fdsfs.fsdf.blo(fsdf.fsfds(fsfs.fs))}
1 myvalue
2 fsdf
3 blo(fsdf.fsfds(fsfs.fs))
显然,我很难提取重复的方法,并且它没有正确验证(老实说,我把它留到最后一步解决),所以允许空括号,并且它不检查一旦括号打开就必须关闭。
谢谢大家
更新
X m.buettner 感谢您的帮助。我快速尝试了您的代码,但出现了一个非常小的问题,尽管我可以绕过它。这个问题与我之前没有发布在这里的代码中的问题相同,当我尝试这个字符串时:
$expression = '${myvalue.fdsfs}';
使用您的模式定义,它显示为:
found
0 ${myvalue.fdsfs}
1 myvalue.fdsfs
2 myvalue
3
4 fdsfs
如您所见,第三行被识别为一个不存在的空格。我不明白为什么会这样,您能否建议我如何解决,或者是因为 PHP 正则表达式的限制而不得不容忍它?
话虽如此,我只能说谢谢您。您不仅回答了我的问题,还尽可能提供了许多关于开发模式时应该遵循的正确路径的建议。
最后一件事,我(愚蠢地)忘记添加一个重要的小案例,即通过逗号分隔的多个参数,所以
$expression = '${classA.methodAA(classB.methodBA(classC.methodCA),classC.methodCB)}';
$expression = '${classA.methodAA(classB.methodBA(classC.methodCA),classC.methodCB,classD.mehtodDA)}';
必须是有效的。
我将其编辑为:
$expressionPattern =
'/
^ # beginning of the string
[$][{] # literal ${
( # group 1, used for recursion
( # group 2 (class name)
[a-z\d]+ # one or more alphanumeric characters
) # end of group 2 (class name)
[.] # literal .
( # group 3 (all intermediate method names)
(?: # non-capturing group that matches a single method name
[a-z\d]+ # one or more alphanumeric characters
[.] # literal .
)* # end of method name, repeat 0 or more times
) # end of group 3 (intermediate method names);
( # group 4 (final method name and arguments)
[a-z\d]+ # one or or more alphanumeric characters
(?: # non-capturing group for arguments
[(] # literal (
(?1) # recursively apply the pattern inside group 1
(?: # non-capturing group for multiple arguments
[,] # literal ,
(?1) # recursively apply the pattern inside group 1 on parameters
)* # end of multiple arguments group; repeat 0 or more times
[)] # literal )
)? # end of argument-group; make optional
) # end of group 4 (method name and arguments)
) # end of group 1 (recursion group)
[}] # literal }
$ # end of the string
/ix';
X Casimir and Hippolyte
你的建议也很好,但使用这段代码时会出现一些复杂的情况。我的意思是说,代码本身很容易理解,但灵活性较差。话虽如此,它也为我提供了许多信息,肯定在未来会有所帮助。
X Denomales
感谢您的支持,但您的代码在我尝试后出现了错误:
$sourcestring='${classA1.methodA0.methodA1.methodB1(classB.methodC(classB.methodD))}';
结果为:
Array
( [0] => 数组 ( [0] => ${classA1方法A0方法A1方法B1(classB方法C(classB方法D))} )
[1] => Array
(
[0] => classA1
)
[2] => Array
(
[0] => methodA0
)
[3] => Array
(
[0] => methodA1.methodB1(classB.methodC(classB.methodD))
)
)
应该是这样的
[2] => Array
(
[0] => methodA0.methodA1
)
[3] => Array
(
[0] => methodB1(classB.methodC(classB.methodD))
)
)
或者
[2] => Array
(
[0] => methodA0
)
[3] => Array
(
[0] => methodA1
)
[4] => Array
(
[0] => methodB1(classB.methodC(classB.methodD))
)
)