我有以下 LaTeX 命令:
\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
使用稍微更复杂的方法和 anchor \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]
请注意,使用这种方法 - 如果您的代码中有多个 autocites
,您将从单个列表中的所有命令获取所有参数。有一些方法可以缓解这种情况,但我认为第一种方法在这种情况下会更干净。
如果您希望能够区分可选参数和强制参数(使用任何方法),请捕获左括号或右括号/大括号以及参数,并检查该字符以找出它是哪种类型。
关于PHP preg_match_all : extract parameters of a command,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18046301/