正则表达式挑战:捕获特定行中的所有数字

RegEx Challenge: Capture all the numbers in a specific row

假设我们有这段文字:

...
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 为这个挑战提供了完美的解决方案。

这是 python 解决方案,但稍后会 post PHP 接收。然而,python 正则表达式和 php 非常相似。

(?<=settingsB=)(\d+(?:\.\d+)?(?:, )?)+

Python:

import re

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

rx = re.compile(r"(?<=settingsB=)(\d+(?:\.\d+)?(?:, )?)+", re.IGNORECASE)
result = rx.search(subject)

if result:
    numString = result.group()

    for n in [f.strip() for f in numString.split(',')]:
        print(n)

PHP

$subject =
    "settingsA=9, 4.2
     settingsB=3, 1.5, 9, 2, 4, 6
     settingsC=8, 3, 2.5, 1";

$pattern = '/(?<=settingsB=)(\d+(?:\.\d+)?(?:, )?)+/i';
preg_match($pattern, $subject, $matches);

if ($matches) {

    $num = explode(",", $matches[0]);

    for ($i = 0; $i < count($num); $i++) {
        print(trim($num[$i]) . "\n");
    }
}

输出:

3
1.5
9
2
4
6

您可以在所需部分使用 PCRE 正则表达式之前使用 \G anchor to glue matches to the end of a previous match. This pattern which also uses \K to reset

(?:settingsB *=|\G(?!^) *,) *\K[\d.]+
  • (?:开一个non-capturing group交替
  • 匹配 settingsB,然后是 * 任意数量的 space,然后是文字 =
  • |\G(?!^) 或从上一场比赛结束但未开始的地方继续
  • *, 并匹配前面有可选 space
  • 的逗号
  • )交替结束(非捕获组)
  • *\K 可选后重置 space
  • [\d.]+ 匹配一位或多位数字和句点。

如果序列包含制表符或换行符,请使用 \s 作为 whitespace 字符 而不是 space.

See demo at regex101 or PHP demo at eval.in

or this more compatible pattern with use of a capturing group 而不是 \K,它应该适用于支持 \G 锚点(Java、.NET、Ruby 的任何正则表达式风格。 .)