文档 ?: 在正则表达式中?

2022-08-30 14:52:40

不久前,我在正则表达式(至少在PHP中)中看到,您可以通过预置来使捕获组不捕获。?:

$str = 'big blue ball';
$regex = '/b(ig|all)/';
preg_match_all($regex, $str, $matches);
var_dump($matches);

输出。。。

array(2) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "big"
    [1]=>
    string(4) "ball"
  }
  [1]=>
  array(2) {
    [0]=>
    string(2) "ig"
    [1]=>
    string(3) "all"
  }
}

在这个例子中,我不关心括号中匹配的内容,所以我附加了()并得到了输出。?:'/b(?:ig|all)/'

array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "big"
    [1]=>
    string(4) "ball"
  }
}

这是非常有用的 - 至少我认为是这样。有时,您只是不想用不必要的值来混淆您的匹配项。

我试图查找文档和这个的官方名称(我称之为非捕获组,但我想我以前听说过)。

作为符号,它似乎很难谷歌搜索。

我还查看了许多正则表达式参考指南,但没有提到。

以 为前缀,并出现在括号内的第一个字符中,会让我相信它与前瞻或前瞻有关。?

那么,这些的正确名称是什么,我在哪里可以了解更多信息?


答案 1

它可以在官方文档的子模式页面上找到。

普通括号实现两个功能的事实并不总是有帮助的。通常,需要分组子模式而没有捕获要求。如果左括号后跟“?:”,则该子模式不执行任何捕获,并且在计算任何后续捕获子模式的数量时不计算在内。例如,如果字符串“白皇后”与模式(?:red|white)(king|queen))匹配,则捕获的子字符串是“白皇后”和“皇后”,并且编号为1和2。捕获的子字符串的最大数量为 99,所有子模式(包括捕获和非捕获)的最大数量为 200。

同样值得注意的是,您可以使用它为子模式设置选项。例如,如果只希望子模式不区分大小写,则可以执行以下操作:

(?i:foo)bar

将匹配:

  • 福巴尔
  • 福巴尔
  • 福巴
  • ...等

但不是

  • fooBar
  • 福巴
  • ...等

哦,虽然官方文档实际上并没有明确命名语法,但它后来确实将其称为“非捕获子模式”(这完全有意义,无论如何我都会这样称呼它,因为它不是真正的“组”,而是一个子模式)......


答案 2

(?:)作为一个整体表示一个非捕获组

Regular-expressions.info 提到这个语法:

左圆括号后面的问号和冒号是特殊语法,可用于告诉正则表达式引擎这对括号不应创建反向引用。请注意,问号 [...] 是使上一个令牌可选的正则表达式运算符。此运算符不能出现在左圆括号之后,因为左括号本身不是有效的正则表达式令牌。因此,在将问号作为运算符以使令牌可选,而将问号作为字符以更改一对圆括号的属性之间不存在混淆。冒号表示我们要进行的更改是关闭捕获反向引用。


推荐