【问题标题】:Documentation for ?: in regex??: 在正则表达式中的文档?
【发布时间】:2011-04-18 06:44:46
【问题描述】:

不久前,我在正则表达式中看到(至少在 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"
  }
}

这非常有用——至少我是这么认为的。有时您只是不想用不必要的值弄乱您的匹配项。

我试图查找文档和它的正式名称(我称它为非捕获组,但我想我以前听说过)。

作为符号,Google 似乎很难找到。

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

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

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

【问题讨论】:

  • +1 因为我不知道 ?:(尽管它使 RegEx 更加不可读)
  • 干得好伙计们,每个人都从我这里得到一分

标签: php regex


【解决方案1】:

(?:) 整体代表一个非捕获组

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

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

【讨论】:

    【解决方案2】:

    可以在官方文档的Subpatterns页面上找到。

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

    还需要注意的是,您可以使用它为子模式设置选项。例如,如果您只希望子模式不区分大小写,您可以这样做:

    (?i:foo)bar
    

    将匹配:

    • foobar
    • Foobar
    • FoObar
    • ...等

    但不是

    • fooBar
    • FooBAR
    • ...等

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

    【讨论】:

    【解决方案3】:

    这是我发现的:

    如果你不使用反向引用, 你可以优化这个常规 表达式转换为 Set(?:Value)?。这 问号和后面的冒号 开口圆括号是特殊的 可以用来告诉 这对正则表达式引擎 方括号不应创建 反向引用。注意问号 在左括号不相关之后 到最后的问号 正则表达式。那个问号是正则表达式 制作前一个令牌的运算符 可选的。该运算符不能出现 在一个开口圆括号之后, 因为一个左括号本身 不是有效的正则表达式令牌。所以, 之间没有混淆 问号作为运算符 令牌可选,问号 作为一个角色来改变 一对圆的性质 括号。冒号表示 我们想做的改变是关闭 捕获反向引用。

    http://www.regular-expressions.info/brackets.html

    【讨论】:

      【解决方案4】:

      它在 php 手册中,我相信任何语言的任何其他近乎完整的正则表达式部分......

      平括号满足两个功能的事实并不总是有用的。经常需要分组子模式而没有捕获要求。如果左括号后跟“?:”,则子模式不进行任何捕获,并且在计算任何后续捕获子模式的数量时不计算在内。

      Source

      【讨论】:

        【解决方案5】:

        我不知道如何使用 ?:,但是使用简单的循环很容易:

        $regex = '/b(ig|all)/';
        $array = array(
            0 => array(0 => 'big', 1 => 'ball'),
            1 => array(0 => 'ig', 1 => 'all')
        );
        foreach ($array as $key => $row) {
            foreach ($row as $val) {
                if (!preg_match($regex, $val)) {
                    unset($array[$key]);
                }
            }
        }
        print_r($array);
        

        【讨论】:

        • 我知道。我只是提出了一个例子。
        【解决方案6】:

        PHP 的preg_match_all 使用PCRE(Perl 兼容的正则表达式)语法,记录在here。非捕获子模式记录在Subpatterns chapter

        会让我相信它与前瞻或后瞻有关。

        不,有很多不同的功能是由开括号问号触发的。 Lookahead/lookbehind 只是您遇到的第一个。

        许多选项必须被压缩到(? 中,而不是赋予它们自己的更易读的语法,这很麻烦,但是有必要将所有内容放入一个序列中,该序列以前本身不是有效的表达式,在旧的正则表达式的变体。

        【讨论】:

          猜你喜欢
          • 2020-08-16
          • 1970-01-01
          • 2011-12-27
          • 1970-01-01
          • 1970-01-01
          • 2018-04-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多