【问题标题】:PHP preg_match_all: extract parameters of a commandPHP preg_match_all:提取命令的参数
【发布时间】:2013-08-05 11:02:23
【问题描述】:

我有以下 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
        )

)

非常感谢任何帮助。

【问题讨论】:

  • 匹配整个命令可能更简单,包括随机的(\{.\}|\[.\])* 变体。然后使用第二个preg_match_all 提取各个参数。或者使用?(DEFINE) 或至少/x 修饰符来制作可管理的正则表达式。

标签: php regex preg-match-all


【解决方案1】:

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

所以首先,匹配整个东西得到参数,然后在第二步提取它们:

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

Workingdemo.

使用稍微复杂的方法和锚点\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]

Working demo.

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

如果您希望能够区分可选参数和强制参数(使用任何方法),请将左括号/大括号与参数一起捕获,并检查该字符以确定它是哪种类型。

【讨论】:

  • 在 PHP 中'\\a'\a,要获得\\a,你需要写'\\\\a'。或者你可以使用<<<'quoting'。 (我认为。):-p
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-16
  • 2023-04-01
  • 2011-03-03
  • 2014-08-04
  • 2016-04-24
  • 2018-12-15
  • 1970-01-01
相关资源
最近更新 更多