我有一个带有正则表达式的小代码片段,用于匹配数值,后跟一个矩形括号中的可选文本,以字符“A”结尾。一个例子是
preg_match_all("/([0-9]+)(?:\[(.*)\])?A/", "123[SomeText]A345[SomeOtherText]A678A", $matches);
print_r($matches);
,预期结果是有三个匹配:
Array
(
[0] => Array
(
[0] => 123[SomeText]A
[1] => 345[SomeOtherText]A
[2] => 678A
)
[1] => Array
(
[0] => 123
[1] => 345
[2] => 678
)
[2] => Array
(
[0] => SomeText
[1] => SomeOtherText
[2] =>
)
)
虽然上面的代码只匹配两次:
Array
(
[0] => Array
(
[0] => 123[SomeText]A345[SomeOtherText]A
[1] => 678A
)
[1] => Array
(
[0] => 123
[1] => 678
)
[2] => Array
(
[0] => SomeText]A345[SomeOtherText
[1] =>
)
)
在给定的正则表达式中,我无法看到我做错了什么。任何修复正则表达式的建议都是受欢迎的。
答案 0 :(得分:3)
您的问题是greediness。量词(如.*
)尽可能多地消耗。由于.
也可以与]
匹配,因此它只会越过第一个结尾]
到最后一个结束.*?
。你可以使用]
使重复不成熟(尽可能少地匹配)。但是在你的情况下有一个更好(更快)的选择。通过从允许的字符中删除它,确保您无法通过结束/([0-9]+)(?:\[([^\]]*)\])?A/
:
/([0-9]+)(?:\[([^]]*)])?A/
请注意,您实际上不必转义结束括号,因为它是类中的第一个字符(并且因为不允许空类,您不需要转义它) - 另一个是在课外,所以它也不能是一个结束括号:
{{1}}
我喜欢哪种变体是品味,我会说。
答案 1 :(得分:2)
。*是贪婪的,所以改变它:
<?php
preg_match_all("/([0-9]+)(?:\[([^A]*)\])?A/", "123[SomeText]A345[SomeOtherText]A678A", $matches);
print_r($matches);
答案 2 :(得分:0)
这种模式怎么样?
\d+(\[.*?\])?A
答案 3 :(得分:0)
好吧,如果你非常确定你的文字不包含'A'字符,那么这应该有效:
'/(\d*)([^A]*)/'
但是如果每个部分都以新部件结尾,而这部件在开头就有一个数字,那么这应该有效:
'/(\d*)([^\d]*)/'
这一行
preg_match_all('/(\d*)([^\d]*)/', "123[SomeText]A345[SomeOtherText]A678A", $matches, PREG_SET_ORDER);
print_r($matches);