【问题标题】:regex matching multiple repeating groups正则表达式匹配多个重复组
【发布时间】:2018-12-26 04:03:14
【问题描述】:

我有以下字符串:

s = " 3434 garbage workorders: 138 waiting, 2 running, 3 failed, 134 completed"

我想解析“工单”之后的状态和计数。我尝试了以下正则表达式:

r = r"workorders:( (\d+) (\w+),?)*"

但这只会返回最后一组。如何返回所有组?

附言我知道我可以在 python 中做到这一点,但想知道是否有纯正则表达式解决方案

>>> s = " 3434 garbage workorders: 138 waiting, 2 running, 3 failed, 134 completed"
>>> r = r"workorders:( (\d+) (\w+),?)*"
>>> re.findall(r, s)
[(' 134 completed', '134', 'completed')]
>>> 

输出应该接近

[('138', 'waiting'), ('2', 'running'), ('3', 'failed'), ('134', 'completed')]

【问题讨论】:

  • 您是如何使用该正则表达式的 - 例如,您是否使用过 re.findall 或其他内容?
  • @JonClements 是的
  • 138 waiting, 2 running, 3 failed, 134 completed 应该是输出?每个都在单独的组中?
  • @GarbageCollector 是的,这样我就可以映射“等待”-> 138 等

标签: python regex


【解决方案1】:

对于示例中的文字,您可以这样尝试:

(?:(\d+) (\w+)(?=,|$))+

说明

  • 非捕获组(?:
  • 一个或多个数字的捕获组(\d+)
  • 空白
  • 一个或多个单词字符的捕获组(\w+)
  • 肯定的lookhead 断言后面是逗号或字符串(?=,|$) 的结尾
  • 关闭非捕获组并重复一次或多次)+

Demo

这会给你:

[('138', 'waiting'), ('2', 'running'), ('3', 'failed'), ('134', 'completed')]

【讨论】:

    【解决方案2】:

    这应该适用于您的特定情况:

    re.findall('[:,] (\d+)', s)
    

    【讨论】:

      【解决方案3】:

      根据我的经验,我发现在尽可能多地处理字符串之后使用正则表达式会更好;任意字符串上的正则表达式只会让人头疼。

      在您的情况下,请尝试拆分“:”(甚至是工作订单:)并在之后获取内容以仅获取状态计数。之后,很容易获得每个状态的计数。

      s = " 3434 garbage workorders: 138 waiting, 2 running, 3 failed, 134 
            completed"
      statuses = s.split(':') #['3434 garbage workorders', ' 138 waiting, 2 running, 3 failed, 134 completed']
      statusesStr = ''.join(statuses[1]) # ' 138 waiting, 2 running, 3 failed, 134 completed'
      
      statusRe = re.compile("(\d+)\s*(\w+)")
      statusRe.findall(statusesStr) #[('138', 'waiting'), ('2', 'running'), ('3', 'failed'), ('134', 'completed')]
      

      编辑:更改表达式以满足期望的结果和更健壮

      【讨论】:

      • 如果您将模式更改为 statusRe = re.compile("(\d+)\s+(\w+)"),它将按照 OP 的要求拆分每个数字/状态对。
      • 啊哎呀,我最初有那个(-ish),但看到问题下的评论有不同的输出。已编辑,谢谢
      【解决方案4】:

      只查看:之后的正则表达式的答案

       re.findall(r'(?: )\d+ \w+')
      

      【讨论】:

        【解决方案5】:

        这将为您提供准确的输出。

        map = re.findall(r'(\d+) ([A-Za-z]+)', s.split("workorders:")[1])
        

        然后你可以破坏这个初始化。

        x = {v: int(k) for k, v in map}
        

        【讨论】:

          猜你喜欢
          • 2020-04-09
          • 2012-11-21
          • 2023-03-19
          • 1970-01-01
          • 2014-03-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多