假设我们有这段文字:

...
settingsA=9, 4.2
settingsB=3, 1.5, 9, 2, 4, 6
settingsC=8, 3, 2.5, 1
...

问题是如何通过一个步骤捕获特定行中的所有数字?

单步表示:
  • 单个正则表达式模式。
  • 单个操作(无循环或拆分等)
  • 所有匹配项都捕获在一个数组中。

  • 假设我要捕获以settingsB=开头的行中存在的所有数字。最终结果应如下所示:
    3
    1.5
    9
    2
    4
    6
    

    我的尝试失败:
    <?php
        $subject =
            "settingsA=9, 4.2
             settingsB=3, 1.5, 9, 2, 4, 6
             settingsC=8, 3, 2.5, 1";
    
        $pattern = '([\d\.]+)(, )?' // FAILED!
        $pattern = '(?:settingsB=)(?:([\d\.]+)(?:, )?)' // FAILED!
        $pattern = '(?:settingsB=)(?:([\d\.]+)(?:, )?)+' // FAILED!
        $pattern = '(?<=^settingsB=|, )([\d+\.]+)' // FAILED!
    
        preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
        if ($matches) {
            print_r($matches);
        }
    ?>
    

    更新1:不幸的是,@Saleem的示例使用多个步骤而不是单个步骤。我并不是说他的例子很糟糕(实际上是可行的),但我想知道是否还有另一种方法以及如何做。有任何想法吗?

    更新2: @bobble bubble为此挑战提供了完美的解决方案。

    最佳答案

    您可以使用 \G anchor将匹配项粘到上一个匹配项的末尾。在期望的部分之前也使用 \K to reset的此模式将与PCRE regex风格一起使用。

    (?:settingsB *=|\G(?!^) *,) *\K[\d.]+
    
  • (?:打开一个non-capturing group进行交替
  • 匹配settingsB,然后是 *任何空间,然后是文字=
  • |\G(?!^)或在上一个比赛结束但未开始的地方继续
  • *,并匹配逗号,并在其前面加上可选的空格
  • )轮换结束(非捕获组)
  • 可选空间后重置
  • *\K
  • [\d.]+匹配一个或多个数字和句点。

  • 如果序列包含制表符或换行符,请使用 \s 代替空格字符。

    See demo at regex101PHP demo at eval.in

    使用or this more compatible pattern而不是\Kcapturing group应该可以在支持\G anchor (Java,.NET,Ruby ...)的任何正则表达式中使用

    10-04 12:02