【问题标题】:making regex more specific to exclude certain characters使正则表达式更具体以排除某些字符
【发布时间】:2019-10-04 16:35:10
【问题描述】:
import re
s = '01.11.11 12/12/1981 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 并且我想提取由 3 个项目分隔的所有日期:或者 1) 句点,例如01.11.11 或 2) 破折号,例如1-22-12 或 3) 反斜杠,例如12/12/1981

为此,我尝试了以下方法

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

它有效,但给了我一些不需要的东西,例如 '1*51*12'22|1|13'

['01.11.11',
 '12/12/1981',
 '1*51*12',
 '22|1|13',
 '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.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',
 '12.23.19']

如何调整 reg 以更具体并获得我想要的输出?

【问题讨论】:

  • 是月份和年份之间的一天还是第一天?到目前为止,如果您根本没有在正则表达式中指定最大值而只使用\d,您将得到的将是 99/99/99,您需要更具体

标签: regex python-3.x string text


【解决方案1】:

而不是在数字集之间匹配. - 这将匹配任何字符 - 只匹配您正在寻找的那些; . - /.

固定正则表达式:

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

还在末尾添加单词边界以避免匹配只有 3 位数年份的日期。

regex101 示例:https://regex101.com/r/0r6jru/2

【讨论】:

  • 谢谢,我忘了测试他的原始字符串!固定。
  • 对前三位数字也失败了,但OP没有提到这一点;否决票已删除。不要忘记更新您的 regex101 链接!
【解决方案2】:

如果您想为整个“日期类似”模式匹配相同的分隔符,您可以使用捕获组和反向引用\1,这样12/12.1981 这样的日期就不会匹配。

请注意,该模式不会验证日期本身。

\b\d{1,2}([./-])\d{1,2}\1(?:\d{4}|\d{2})\b
  • \b字边界
  • \d{1,2}匹配1-2位数字
  • ([./-]) 捕获组 1,匹配 . /-
  • \d{1,2}\1 匹配 1-2 位数字和对第一个捕获的分隔符的反向引用
  • (?:\d{4}|\d{2}) 匹配 4 位或 2 位数字
  • \b字边界

Regex demo | Python demo

例如使用re.finditer(因为 re.findall 将返回作为分隔符的捕获组)

import re
reg = r"\b\d{1,2}([./-])\d{1,2}\1(?:\d{4}|\d{2})\b"
s = "01.11.11 12/12/1981 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.finditer(reg, s)
for matchNum, match in enumerate(matches, start=1):
    print(match.group())

【讨论】:

  • 在 findall 中反向引用??这意味着有一个捕获的组,因此这不起作用
【解决方案3】:

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

此正则表达式将匹配您所有的测试用例,并过滤不正确的年份,例如12.23.192

Try it here!

【讨论】:

  • 这需要23\23\201 那是哪个日期?
  • OP 没有具体说明他们想要MM-DD-YYYY 还是DD-MM-YYYY - 另外,您是否测试过23\23\201?不匹配。
猜你喜欢
  • 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
相关资源
最近更新 更多