preg_match - 忽略可选的括号

preg_match - ignore optional parentheses

我有以下字符串,其中包含与 preg_match 匹配的可选括号。键是输入,值是期望的输出:

$strings = [
  '(prefix) (string in parens)'   => 'string in parens',
  '(prefix) string not in parens' => 'string not in parens',
  '(prefix) parens (at the end)'  => 'parens (at the end)',
];

假设我想一次完成此操作 preg_match,我目前有以下内容:

preg_match('/^\(prefix\) (\((.+)\)|.+)$/', $input, $matches);
$output = (isset($matches[2]) ? $matches[2] : $matches[1]);

这可行,但需要一个单独的子模式来检测所看到的格式。有没有更好的方法在单个子模式中执行此操作?假设在子模式的两端都有可选的括号是不够的,因为可能有我想包含的括号。

我知道我还有其他选项,例如分别去除前缀和括号,但我想知道是否有更好的方法可以在不先更改逻辑的情况下执行此操作。

在单个捕获组中获得所有匹配的一个选项是使用 branch reset group 捕获从左括号到右括号的前缀后,或不带括号但仅可选地匹配它的行结束。

^\(prefix\)\h(?|\(([^()\n]+)\)|([^()\n]+(?:\([^()\n]+\))?))$
  • ^ 字符串开头
  • \(prefix\)\h 匹配 (prefix) 和水平空白字符
  • (?|分支重置组
    • \(([^()\n]+)\) 直接匹配 ( ... ) 并在第 1 组中捕获
    • 之间的内容
    • |
    • ( 捕获组 2
      • [^()\n]+ 匹配除 ( ) 或换行符之外的任何字符
      • (?:\([^()\n]+\))? 可选匹配 (...)
    • ) 关闭组 2
  • )关闭分支重置组
  • $ 字符串结束

Regex demo

或者正如您所指出的,此模式 ^\(prefix\) (?|\((.+)\)|(.+))$ 将是广泛匹配以捕获括号之间的内容或后面的所有内容。