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

Php 正则表达式挑战:捕获特定行中的所有数字,php,regex,text,notepad++,pcre,Php,Regex,Text,Notepad++,Pcre,假设我们有以下文本: ... 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
...
问题是如何使用单个步骤捕获特定行中的所有数字?

单步是指:

  • 单一正则表达式模式
  • 单次操作(无回路或拆分等)
  • 在一个数组中捕获所有匹配项
假设我想捕获以
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解决方案,但稍后将发布PHP rx。然而,python正则表达式和php非常相似

(?<=settingsB=)(\d+(?:\.\d+)?(?:, )?)+
可以使用将匹配项粘附到上一个匹配项的末尾。此模式也在所需部件与PCRE regex flavor一起使用之前使用

(?:settingsB *=|\G(?!^) *,) *\K[\d.]+
  • (?:
    打开一个用于替换的
  • 匹配
    settingsB
    ,后跟
    *
    任意大小的空格,后跟literal
    =
  • |\G(?!^)
    或在上一个匹配结束但未开始的位置继续
  • *,
    并匹配前面带有可选空格的逗号
  • 交替结束(非捕获组)
  • *\K
    在可选空格后重置
  • [\d.]+
    匹配一个或多个数字和句点
如果序列包含制表符或换行符,请使用空格字符而不是空格


使用替代的
\K
应该可以在任何支持
\G
锚(Java、.NET、Ruby…)的正则表达式风格中工作,请提及您的环境、语言。e、 PHP、python、java、JavaScript等,甚至编辑器、记事本++我猜是一个通用引擎,没有语言,除了正则表达式。是的,但这将是一个多阶段的解决方案。capture+tokenizerI发布了python解决方案,因为php目前不可用。但是python和php正则表达式非常相似,我将其粘贴到regex101.com中,它只匹配最后一个数字,即使正则表达式设置为python也是如此。“知道为什么吗?”萨利姆,谢谢你的回答,但一定有更好的解决办法。我希望在不拆分的情况下返回数组中的结果,例如
(numString.split)
。让正则表达式进行拆分。有什么想法吗?@JerryJeremiah,因为regex101只显示最后一组。请看@OlavH,是的,我同意。应该有更好的解决方案,但在短时间内总比没有好:)只是为了好玩:你知道
过早优化是万恶之源
一个解决方案是应用两个不同的正则表达式。一个是像最初一样捕获整个字符串,然后在最后一次捕获的结果上应用另一个正则表达式来消除coma`,`简直太完美了!这就是我所说的regex魔术。谢谢你的解决方案。
$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
(?:settingsB *=|\G(?!^) *,) *\K[\d.]+