【问题标题】:Capture only the numbers from a string beginning with 's_' and containing a mix of numbers and letters仅捕获以 's' 开头并包含数字和字母混合的字符串中的数字
【发布时间】:2017-06-13 23:20:39
【问题描述】:

我想从这个字符串中提取所有数字:'s_0a1f2d4e3c10b'。字符串必须遵循此模式 's_NumberLetterNumberLetter...' 我写了这个匹配整个字符串的正则表达式:

/^q_(?:\d+[a-f])+$/

问题是我不知道如何仅捕获数字。当我在 \d+ 周围加上括号时,正则表达式仅匹配最后一个数字(10)。 这是带括号的正则表达式:

^q_(?:(\d+)[a-f])+$

当然我可以使用preg_match_all('/\d+/', 's_0a1f2d4e3c10b', $matches),但我希望字符串以“s_”开头,并且我只想使用一个正则表达式(如果可能的话)。

我想要的来自s_0a1f2d4e3c10b的输出:

array(0, 1, 2, 4, 3, 10)

【问题讨论】:

    标签: php regex preg-match-all


    【解决方案1】:

    您需要正则表达式中的“继续”元字符 (\G) 才能在单个 preg_ 调用中干净地执行此任务。

    只有当子字符串以s_ 开头时,匹配才能开始。然后匹配只能在保持交替数字和小写字母模式的情况下继续。

    \G 实际上允许从字符串的开头或最后一次匹配完成的位置进行匹配。要拒绝从字符串开头匹配的功能,请添加一个包含插入符号 ((?!^)) 的否定前瞻。

    \K 意味着重新开始这个全字符串匹配(或者换句话说,“忘记”任何以前匹配的字符)。这避免了使用捕获组,否则会不必要地膨胀匹配的输出数组。

    代码:(Demo)

    $tests = [
        'This string s_0a1f2d4e3c10b is foo.',
        's_1a23b456c789',
        'b_9d9d9d9d9d',
        's_1e2f3a4b'
    ];
    
    foreach ($tests as $test) {
        var_export(
            preg_match_all(
                '~(?:s_|\G(?!^)[a-z]+)\K\d+~',
                $test,
                $matches
            )
            ? $matches[0]
            : []
        );
        echo "\n---\n";
    }
    

    输出:

    ['0', '1', '2', '4', '3', '10']
    ---
    ['1', '23', '456', '789']
    ---
    []
    ---
    ['1', '2', '3', '4']
    ---
    

    【讨论】:

      【解决方案2】:

      不确定您要的是哪个结果,因为您似乎想保留 s_,但将数字(不是数字)分隔成值。它是一个字符串或一个数字列表,而不是两者。

      preg_match_all('/s_\d+|\d+/', 's_0a1f2d4e3c10b', $matches) 将返回一个数组,其中第一个值保留s_ 开头。
      preg_match_all('/s_\d+|\d+/', 's_0a1f2d4e3c10b', $matches) 将返回一个数组,第一个值s_然后是数字。
      您建议的 preg_match_all('/\d+/', 's_0a1f2d4e3c10b', $matches) 将仅返回数组中的数字,如果将它们连接到字符串,则可以添加 s_ 前缀。

      【讨论】:

      • 谢谢!我希望 preg_match_all 仅在字符串以“s_”开头时才返回数字数组。我最终使用了 2 个正则表达式:一个用于检查字符串,另一个用于提取数字。
      【解决方案3】:

      你可以像这样使用 preg_replace:

      $count = null;
      $returnValue = preg_replace('/[^0-9]+/', '', 's_0a1f2d4e3c10b', -1, $count);
      

      这将从字符串中删除所有非数字字符。

      $returnValue 将包含 '0124310'$count 将包含 7(删除的字符数)

      【讨论】:

      • 非常感谢您的回答。但是我不知道如何将这些数字拆分为数字,我的意思是,现在 10 可以被视为 1 和 0
      • @winapiwrapper 您没有在最初的帖子中指定您想要一个包含在字符串中找到的数字的数组(您后来澄清了收到的 cmets),所以我的建议是获取根据我在您最初发布时对您的要求的理解,删除了所有非数字字符的字符串。无论如何,您现在似乎已经解决了您的问题,所以现在一切都很好,我建议您接受对您最有帮助的其他答案之一:-)
      猜你喜欢
      • 1970-01-01
      • 2023-02-08
      • 1970-01-01
      • 1970-01-01
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      • 2011-09-24
      • 1970-01-01
      相关资源
      最近更新 更多