0

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

4 回答 4

3

你的问题是贪婪。量词(如.*)尽可能地消耗。因为.也可以匹配],所以它只是从第一个结束]到最后一个结束。您可以使用.*?. 但是在您的情况下,有一个更好(更快)的选择。通过从允许的字符中删除它,确保您不能越过关闭]

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

工作演示。

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

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

工作演示。

我会说,您更喜欢哪种变体取决于口味。

于 2013-08-12T11:28:35.983 回答
2

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

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

试试看:http: //3v4l.org/BZgmH

于 2013-08-12T11:28:21.793 回答
0

这个模式怎么样?

\d+(\[.*?\])?A
于 2013-08-12T11:28:15.233 回答
0

好吧,如果您很确定您的文本不包含“A”字符,那么这应该可以:

'/(\d*)([^A]*)/'

但是如果每个部分都以开头有数字的新部分结尾,这应该有效:

'/(\d*)([^\d]*)/'

用这条线

preg_match_all('/(\d*)([^\d]*)/', "123[SomeText]A345[SomeOtherText]A678A", $matches, PREG_SET_ORDER);
print_r($matches);
于 2013-08-12T11:50:05.957 回答