问题描述
我有以下字符串,其中包含与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]);
这可行,但是需要一个单独的子模式来检测看到的格式。有没有更好的方法可以在单个子模式中执行此操作?仅在子模式的任一端假设可选的括号是不够的,因为可能会有一些我想包括的括号。
我知道我还有其他选择,例如分别去除前缀和括号,但是我想知道是否有更好的方法来执行此操作而不先更改逻辑。
解决方法
在单个捕获组中获得所有匹配项的一个选项是使用来捕获从开头到结尾括号后的前缀,或者使用没有括号但仅在末尾匹配的行。
^\(prefix\)\h(?|\(([^()\n]+)\)|([^()\n]+(?:\([^()\n]+\))?))$
-
^
字符串的开头 -
\(prefix\)\h
匹配(prefix)
和一个水平空格字符 -
(?|
分支重置组-
\(([^()\n]+)\)
直接从(
...)
进行匹配,并在第1组中捕获介于两者之间的内容 -
|
或 -
(
捕获组2-
[^()\n]+
匹配(
)
或换行符以外的任何字符 -
(?:\([^()\n]+\))?
(可选)匹配(
...)
-
-
)
关闭第2组
-
-
)
关闭分支重置组 -
$
字符串结尾
或者正如您所指出的那样,此模式^\(prefix\) (?|\((.+)\)|(.+))$
是广泛的匹配项,可以捕获括号之间的内容或后面所有内容。