我的正则表达式应匹配3次,但只匹配两次(PHP)

时间:2013-08-12 11:23:46

标签: php regex

我有一个带有正则表达式的小代码片段,用于匹配数值,后跟一个矩形括号中的可选文本,以字符“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] => 
        )
)

在给定的正则表达式中,我无法看到我做错了什么。任何修复正则表达式的建议都是受欢迎的。

4 个答案:

答案 0 :(得分:3)

您的问题是greediness。量词(如.*)尽可能多地消耗。由于.也可以与]匹配,因此它只会越过第一个结尾]到最后一个结束.*?。你可以使用]使重复不成熟(尽可能少地匹配)。但是在你的情况下有一个更好(更快)的选择。通过从允许的字符中删除它,确保您无法通过结束/([0-9]+)(?:\[([^\]]*)\])?A/

/([0-9]+)(?:\[([^]]*)])?A/

Working demo.

请注意,您实际上不必转义结束括号,因为它是类中的第一个字符(并且因为不允许空类,您不需要转义它) - 另一个是在课外,所以它也不能是一个结束括号:

{{1}}

Working demo.

我喜欢哪种变体是品味,我会说。

答案 1 :(得分:2)

。*是贪婪的,所以改变它:

<?php
preg_match_all("/([0-9]+)(?:\[([^A]*)\])?A/", "123[SomeText]A345[SomeOtherText]A678A", $matches);
print_r($matches);

尝试一下:http://3v4l.org/BZgmH

答案 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);