PHP preg_match_all:提取命令的参数

PHP preg_match_all:提取命令的参数,php,regex,preg-match-all,Php,Regex,Preg Match All,我有以下命令: \autocites[][]{}[][]{} 如果[]中的参数是可选的,则{}中的其他参数是必需的。\autocites命令可以通过以下附加参数组进行扩展: \autocites[a1][a2]{a3}[b1][b2]{b3} \autocites[a1][a2]{a3}[b1][b2]{b3}[c1][c2]{c3} ... 它也可以这样使用: \autocites{a}{b} \autocites{a}[b1][]{b3} \autocites{a}[][b2]{b3}

我有以下命令:

\autocites[][]{}[][]{}
如果
[]
中的参数是可选的,则
{}
中的其他参数是必需的。
\autocites
命令可以通过以下附加参数组进行扩展:

\autocites[a1][a2]{a3}[b1][b2]{b3}
\autocites[a1][a2]{a3}[b1][b2]{b3}[c1][c2]{c3}
...
它也可以这样使用:

\autocites{a}{b}
\autocites{a}[b1][]{b3}
\autocites{a}[][b2]{b3}
...
我想使用PHP中的正则表达式来提取它的参数。这是我第一次尝试:

/\\autocites(\[(.*?)\])(\[(.*?)\])(\{(.*?)\})(\[(.*?)\])(\[(.*?)\])(\{(.*?)\})/
虽然如果
\autocites
仅包含两组三个参数,则此方法可以正常工作,但我无法找出如何使其在未知数量的参数下工作

我还尝试使用以下表达式:

/\\autocites((\[(.*?)\]\[(.*?)\])?\{(.*?)\}){2,}/
这一次,我能够匹配更多的参数,但我无法提取所有值,因为PHP总是给我最后三个参数的内容:

Array
(
    [0] => Array
        (
            [0] => \autocites[a][b]{c}[d][e]{f}[a][a]{a}
        )

    [1] => Array
        (
            [0] => [a][a]{a}
        )

    [2] => Array
        (
            [0] => [a][a]
        )

    [3] => Array
        (
            [0] => a
        )

    [4] => Array
        (
            [0] => a
        )

    [5] => Array
        (
            [0] => a
        )

)

非常感谢您的帮助。

您必须分两步完成此操作。只有.NET可以检索任意数量的捕获。在所有其他风格中,结果捕获的数量由模式中的组数固定(重复组只会覆盖以前的捕获)

因此,首先,匹配整个对象以获得参数,然后在第二步中提取它们:

preg_match('/\\\\autocites((?:\{[^}]*\}|\[[^]]*\])+)/', $input, $autocite);
preg_match_all('/(?|\{([^}]*)\}|\[([^]]*)\])/', $autocite[1], $parameters);
// $parameters[1] will now be an array of all parameters

使用稍微复杂一点的方法和锚定
\G
我们也可以一次完成所有工作,通过使用任意数量的匹配而不是捕获:

preg_match_all('/
    (?|             # two alternatives whose group numbers both begin at 1
      \\\\autocites  # match the command
      (?|\{([^}]*)\}|\[([^]]*)\])
                    # and a parameter in group 1
    |               # OR
      \G            # anchor the match to the end of the last match
      (?|\{([^}]*)\}|\[([^]]*)\])
                    # and match a parameter in group 1
    )
    /x',
    $input,
    $parameters);
// again, you'll have an array of parameters in $parameters[1]

请注意,使用这种方法-如果代码中有多个
自动站点
,则可以从单个列表中的所有命令中获取所有参数。有一些方法可以缓解这种情况,但我认为在这种情况下,第一种方法会更干净


如果您希望能够区分可选参数和必需参数(使用任何方法),请捕获开头或结尾括号/大括号以及参数,并对照该字符检查它是哪种类型。

可能更简单的方法是只匹配整个命令,包括random
(\{.\}.\[.\])*
变体。然后使用第二个
preg_match_all
提取各个参数。或者使用
?(DEFINE)
或至少使用
/x
修饰符来生成一个可管理的正则表达式。在PHP
中,\\a'
\a
,要获得
\\a
您需要编写
'\\\a'
。或者您可以使用