【问题标题】:Extract all numbers (int and floats) after specific word提取特定单词后的所有数字(整数和浮点数)
【发布时间】:2021-12-19 04:38:03
【问题描述】:

假设我有以下字符串:

str = """
         HELLO 1 Stop #$**& 5.02‼️ 16.1 
         regex

         5 ,#2.3222
      """

我想导出所有数字,无论是 int 还是 float 在单词“stop”之后,不区分大小写。所以预期的结果是:

[5.02, 16.1, 5, 2.3222]

到目前为止,我最远的是使用其他帖子中的 PyPi 正则表达式:

regex.compile(r'(?<=stop.*)\d+(?:\.\d+)?', regex.I)

但这个表达式只给了我 [5.02, 16.1]

【问题讨论】:

  • 到目前为止你尝试过什么?您有具体的问题吗?
  • 是的,问题已更新

标签: python regex string re


【解决方案1】:

你可以使用:

inp = """
HELLO 1 Stop #$**& 5.02‼️ 16.1 
regex

5 ,#2.3222"""

nums = []
if re.search(r'\bstop\b', inp, flags=re.I):
    inp = re.sub(r'^.*?\bstop\b', '', inp, flags=re.S|re.I)
    nums = re.findall(r'\d+(?:\.\d+)?', inp)

print(nums)  # ['5.02', '16.1', '5', '2.3222']

上面的if 逻辑确保我们仅在确定Stop 出现在输入文本中时才尝试填充数字数组。否则,默认输出只是一个空数组。如果Stop 确实出现了,那么我们在使用re.findall 查找之后出现的所有数字之前去掉字符串的前导部分。

【讨论】:

    【解决方案2】:
    import re
    
    _string = """
              HELLO 1 Stop #$**& 5.02‼️ 16.1
              regex
    
              5 ,#2.3222
           """
    
    start = _string.find("Stop") + len("Stop")
    print(re.findall("[-+]?\d*\.?\d+", _string[start:]))   # ['5.02', '16.1', '5', '2.3222']
    
    

    【讨论】:

      【解决方案3】:

      您只会得到前 2 个数字,因为 .* 不匹配换行符。

      您可以将更新标志添加到regex.I | regex.S 以使点匹配换行符。

      import regex
      
      text = """
               HELLO 1 Stop #$**& 5.02‼️ 16.1 
               regex
      
               5 ,#2.3222
            """
      
      pattern = regex.compile(r'(?<=\bstop\b.*)\d+(?:\.\d+)?', regex.I | regex.S)
      
      print(regex.findall(pattern, text))
      

      输出

      ['5.02', '16.1', '5', '2.3222']
      

      查看Python demo


      如果你想打印“stop”这个词之后的数字,你也可以使用pythonre匹配stop,然后将后面的全部捕获到一个组中。

      然后你可以取第 1 组的值,并找出所有的数字。

      import re
       
      text = """
               HELLO 1 Stop #$**& 5.02‼️ 16.1 
               regex
       
               5 ,#2.3222
            """
      pattern = r"\bStop\b(.+)"
       
      m = re.search(pattern, text, re.S|re.I)
       
      if m:
          print(re.findall(r"\d+(?:\.\d+)*", m.group(1)))
      

      输出

      ['5.02', '16.1', '5', '2.3222']
      

      【讨论】:

      • 哈!我现在删除的答案可能看起来很熟悉。
      • @CarySwoveland 你也可以使用内联修饰符:-)
      • \G 可能更适合 (+1),可变的后视很昂贵。
      【解决方案4】:

      还有一个,虽然是更新的regex 模块:

      (?:\G(?!\A)|Stop)\D+\K\d+(?:\.\d+)?
      

      a demo on regex101.com


      Python,这可能是

      import regex as re
      
      string = """
               HELLO 1 Stop #$**& 5.02‼️ 16.1 
               regex
      
               5 ,#2.3222
            """
      
      pattern = re.compile(r'(?:\G(?!\A)|Stop)\D+\K\d+(?:\.\d+)?')
      
      numbers = pattern.findall(string)
      print(numbers)
      

      并且会产生

      ['5.02', '16.1', '5', '2.3222']
      

      不要以内置函数命名变量,例如 strlistdict 等。


      如果您需要更进一步并将搜索限制在某些范围内(例如,Stopend 之间的所有数字),您也可以使用

      (?:\G(?!\A)|Stop)(?:(?!end)\D)+\K\d+(?:\.\d+)?
      #           ^^^        ^^^
      

      查看另一个demo on regex101.com

      【讨论】:

      • 不错,Jan. ^.*\bStop\b(\D*\K\d+(?:\.\d+)?)|\G(?1) 似乎也适用于 PCRE2 (Demo),其中 (?1) 是一个重用捕获组 1 中代码的子例程,但我不能让它工作here,但是...
      • ...您的正则表达式工作正常there。您发现我的变体有问题吗?
      • @CarySwoveland:它真的不起作用,请参阅here(您有两个很多匹配项,请参阅"1")。您可以让它与匹配的对象一起工作。无法访问在递归内部匹配的捕获组,请参阅documentation。这有帮助吗?
      • 是的,很有帮助,但我仍然不明白为什么它适用于 PCRE2 但不适用于 Tio。
      • @CarySwoveland 这里是the correct demo of your solution。您可能想在此处使用rgx = r'(?ms)^.*?\bStop\b(\D*\K\d+(?:\.\d+)?)|\G(?1)',可能与[x.group() for x in re.finditer(rgx, s)] 一起使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多