【问题标题】:modification of making regex more specific to exclude certain characters修改使正则表达式更具体以排除某些字符
【发布时间】:2019-10-06 21:05:00
【问题描述】:
import re
s = '01.20/15 01/20.1915 1/1/19 01.11.11 1.8-24 3-4.12 01/20-09 12/12/1981 12-01/2001 1*51*12  22|1|13 03-02-1919 1-22-12 or 01-23-18 or 03-23-1984 01.11.18 or 2.2.17 or 02.02.18 or 12.1.16 12.23.1943 01-23-11 not 12.23.192 not 02.02.1'

我有以下字符串s,这是对making regex more specific to exclude certain characters的修改

我想获取所有日期,所以我使用

reg = r'\b((?:\d{1,2}(?:\.|\/|-)){2}(?:\d{4}|\d{2}))\b'
r1 = re.findall(reg,s)
r1

我得到了

['01.20/15',
 '01/20.1915',
 '1/1/19',
 '01.11.11',
 '1.8-24',
 '3-4.12',
 '01/20-09',
 '12/12/1981',
 '12-01/2001',
 '03-02-1919',
 '1-22-12',
 '01-23-18',
 '03-23-1984',
 '01.11.18',
 '2.2.17',
 '02.02.18',
 '12.1.16',
 '12.23.1943',
 '01-23-11']

这与我想要的很接近,但我不想要混合了 ./- 的字符串,例如'01.20/15''3-4.12'3-4.12

我想要的输出是这样的

['1/1/19',
 '01.11.11',
 '12/12/1981',
 '03-02-1919',
 '1-22-12',
 '01-23-18',
 '03-23-1984',
 '01.11.18',
 '2.2.17',
 '02.02.18',
 '12.1.16',
 '12.23.1943',
 '01-23-11']

其中不包含任何混合有./- 的数字,例如'01.20/15''3-4.12'

我也试过修改reg

reg = r'\b((?:\d{1,2}(?:\.\b|\\b/|-\b)){2}(?:\d{4}|\d{2}))\b'

但这并不完全有效

如何进一步修改reg 以获得我想要的输出?

【问题讨论】:

    标签: regex python-3.x string text


    【解决方案1】:

    我猜这里也许反向引用不是一个坏主意:

    \b([0-9]{1,2}([./-])[0-9]{1,2}\2[0-9]{2,4})\b
    

    \b[0-9]{1,2}([.\/-])[0-9]{1,2}\1(?:[0-9]{2}|[0-9]{4})\b
    

    Demo

    测试

    import re
    
    regex = r'\b([0-9]{1,2}([./-])[0-9]{1,2}\2\d{2,4})\b'
    string = '''
    01.20/15 01/20.1915  01.11.11 1.8-24 3-4.12 01/20-09 12/12/1981 12-01/2001 1*51*12  22|1|13 03-02-1919 1-22-12 or 01-23-18 or 03-23-1984 01.11.18 or 2.2.17 or 02.02.18 or 12.1.16 12.23.1943 01-23-11 not 12.23.192 not 02.02.1
    
    '''
    
    matches = re.findall(regex, string)
    
    output = []
    for match in matches:
        output.append(match[0])
    
    print(output)
    

    输出

    ['01.11.11', '12/12/1981', '03-02-1919', '1-22-12', '01-23-18', '03-23-1984', '01.11.18', '2.2.17', '02.02.18', '12.1.16', '12.23.1943', '01-23-11', '12.23.192']

    Demo

    【讨论】:

    • 感谢您的代码。这与我想要的很接近,除了我正在寻找['01.11.11'' 格式而不是'[(01.11.11', '.')
    • 谢谢!实际上这段代码很接近,但它正在捕获它不应该捕获的12.23.192'
    • 好点。我不想要像45-90-4000 这样的值。我只想要约会。但我也会问另一个问题来处理这个问题
    【解决方案2】:

    可以将 findall() 与单个捕获组一起使用,而不是使用 backref,类似于

    \b((?:\d{1,2}\.\d{1,2}\.|\d{1,2}/\d{1,2}/|\d{1,2}-\d{1,2}-)(?:\d{2}|\d{4}))\b

    https://regex101.com/r/V2AXPj/1

    展开

     \b 
     (                             # (1 start)
          (?:
               \d{1,2} \. \d{1,2} \. 
            |  
               \d{1,2} / \d{1,2} /
            |  
               \d{1,2} - \d{1,2} -
          )
          (?: \d{2} | \d{4} )
     )                             # (1 end)
     \b
    

    【讨论】:

      【解决方案3】:

      这可能会让你更接近你正在寻找的东西:

      RE = r'((?:\d{1,2}(?:\.|\/|-)){2}\d{1,4})'
      

      这将匹配提供的大部分输入,但以下字符串除外:

      11-11-12-13-15.1645
      01-01-11-12
      

      此正则表达式将捕获第一个示例的 11-11-1213-15.1645,以及第二个示例的 01-01-11。您可以对较长的字符串进行一些预处理,以便在 -|/|. 分隔符上进行拆分。通过拆分第一个分隔符,然后是第二个,... 直到您使用 re.match(post_split[0])re.match(post_split[1]) 找到匹配项。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        • 2015-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多