【问题标题】:regex to capture overlapping matches preceding any number with more than 4 digits正则表达式捕获任何超过 4 位数字之前的重叠匹配
【发布时间】:2019-04-04 15:35:04
【问题描述】:

我正在编写一个正则表达式来选择以下文本中超过 4 个数字的数字之前存在的 30 个字符。这是我的代码:

text = "I went and I bought few tickets and ticket numbers 100000,100001 and 100002.I bought them for 200,300 and 400 USD. Box office collections were 55555555 USD"

reg=".{0,30}(?:[\d]+[ .]?){5,}"
regc=re.compile(reg)
res=regc.findall(text)

这给出了以下部分结果

我只得到 100000 之前的 30 个字符。

如何获得 100001 之前的 30 个字符以及如何获得 100002 之前的 30 个字符?

【问题讨论】:

  • 预期的结果是什么?通过尝试修复它,我得到了['D. Box office collections were 55555555', 'cket numbers 100000,100001 and 100002', 'ets and ticket numbers 100000,100001', 'few tickets and ticket numbers 100000']
  • 您是否必须使用正则表达式来捕获字符串中所有超过 4 位数字前面的字符?
  • @Wiktor 是的,这会有所帮助.. 你还可以帮我提取 100001 和 100002 以及 100000 就像在第一个字符串中一样..
  • @benvc 是的,我想捕获 4 位数字之前的字符

标签: python regex


【解决方案1】:

您正在寻找前面的任何 30 个字符,但换行符除外,?= 积极向前看,但不包括在捕捉组中

/.{30}(?=100001)/g

https://regexr.com/4293v

【讨论】:

    【解决方案2】:

    由于您需要重叠匹配,因此您需要使用环视。但是,re 中的lookbehinds 是固定宽度的,因此,您可以利用hack:反转字符串,使用带有前瞻的正则表达式,然后反转匹配项:

    import re
    rev_rx = r'((?:\d+[ .]?){5,})(?=(.{0,30}))'
    text="I went and I bought few tickets and ticket numbers 100000,100001 and 100002.I bought them for 200,300 and 400 USD. Box office collections were 55555555 USD"
    results = [ "{}{}".format(y[::-1], x[::-1]) for x, y in re.findall(rev_rx, text[::-1]) ]
    print(results)
    # => ['D. Box office collections were 55555555', 'cket numbers 100000,100001 and 100002', 'ets and ticket numbers 100000,100001', 'few tickets and ticket numbers 100000']
    

    请参阅Python demo

    ((?:\d+[ .]?){5,})(?=(.{0,30})) 正则表达式匹配并捕获到组 1 五个或更多的 1+ 数字序列和可选的空格或逗号。然后,正向先行检查字符串中是否有 0 到 30 个字符。子字符串被捕获到第 2 组。因此,您只需将反转的第 2 组和第 1 组值连接起来即可获得所需的匹配项。

    【讨论】:

      【解决方案3】:

      您可以通过将一些简单的正则表达式与字符串方法相结合来实现此目的,以获取位于任何超过 4 位数字前面的 30 个字符(而不是使用更复杂的正则表达式来查找匹配项并捕获所需的字符)。

      下面的例子使用正则表达式查找所有超过 4 位的数字,然后使用str.find() 获取每个匹配项在原文中的位置,这样就可以对前面的 30 个字符进行切片:

      import re
      
      text = "I went and I bought few tickets and ticket numbers 100000,100001 and 100002.I bought them for 200,300 and 400 USD. Box office collections were 55555555 USD"
      
      patt = re.compile(r'\d{5,}')
      nums = patt.findall(text)
      matches = [text[:text.find(n)][-30:] for n in nums]
      
      print(matches)
      # OUTPUT (shown on multiple lines for readability)
      # [
      #     'ew tickets and ticket numbers ',
      #     'ets and ticket numbers 100000,',
      #     'ket numbers 100000,100001 and ',
      #     '. Box office collections were '
      # ]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-13
        • 1970-01-01
        • 2010-12-12
        • 2018-05-11
        • 2023-03-15
        • 1970-01-01
        • 1970-01-01
        • 2017-11-10
        相关资源
        最近更新 更多