【问题标题】:Regex To Alter Date String正则表达式更改日期字符串
【发布时间】:2019-10-16 19:36:21
【问题描述】:

我对python有点陌生,对于这个作业,我们被要求使用一个正则表达式来解决每个提示。我已经完成了提示 A-C,但现在我卡在了提示 D。 提示如下:

d。使用正则表达式的替换,将“2019 年 5 月 29 日”或“2019 年 5 月 29 日”格式的日期转换为“19 年 5 月 29 日”。

要匹配的有效日期格式包含以下元素: •月份必须是常见的三字母月份缩写,以大写字母开头,后跟两个小写字母:Jan、Feb、Mar、Apr、May、Jun、Jul、Aug、Sep、Oct、Nov、Dec.
•日期可能是一位或两位数。不必检查有效日期,可以接受带有前导零的日期,例如 03。 •年份正好是四位数。
• 月份和日期由一个或多个空格分隔。日期和年份也由一个或多个空格分隔,但允许紧跟在日期之后的可选逗号(日期和逗号之间不允许有空格)

我坚持的是:我不确定在 r"..." 语句中放什么(参考代码),现在我得到一个错误 "re.error: bad escape \ w 在位置 0",如果我们可以修复错误或找到另一种方法来做到这一点,同时保持 substr = r"..." 我真的很感激!谢谢!

注意: --我的 re.compile 代码工作得很好,在我弄乱子字符串来更改输出之前,它接受了这种情况。它只是没有转换它,因为我还没有编写转换字符串。 --目前我处理日期的方式不是很传统,我计划在得到一些有用的东西之后再做这件事。

代码:

import re

d = re.compile(r"^((Jan)\s+[1-31],\s+\d{4})$|"
               r"^((Jan)\s+[1-31]\s+\d{4})$|"
               r"^((Feb)\s+[1-28],\s+\d{4})$|"
               r"^((Feb)\s+[1-28]\s+\d{4})$|"
               r"^((Feb)\s+[1-29],\s+\d{4})$|" #ask prof about leap years
               r"^((Feb)\s+[1-29]\s+\d{4})$|"  #ask prof about leap years
               r"^((Mar)\s+[1-31],\s+\d{4})$|"
               r"^((Mar)\s+[1-31]\s+\d{4})$|"
               r"^((Apr)\s+[1-30],\s+\d{4})$|"
               r"^((Apr)\s+[1-30]\s+\d{4})$|"
               r"^((May)\s+[1-31],\s+\d{4})$|"
               r"^((May)\s+[1-31]\s+\d{4})$|"
               r"^((Jun)\s+[1-30],\s+\d{4})$|"
               r"^((Jun)\s+[1-30]\s+\d{4})$|"
               r"^((Jul)\s+[1-31],\s+\d{4})$|"
               r"^((Jul)\s+[1-31]\s+\d{4})$|"
               r"^((Aug)\s+[1-31],\s+\d{4})$|"
               r"^((Aug)\s+[1-31]\s+\d{4})$|"
               r"^((Sep)\s+[1-30],\s+\d{4})$|"
               r"^((Sep)\s+[1-30]\s+\d{4})$|"
               r"^((Oct)\s+[1-31],\s+\d{4})$|"
               r"^((Oct)\s+[1-31]\s+\d{4})$|"
               r"^((Nov)\s+[1-30],\s+\d{4})$|"
               r"^((Nov)\s+[1-30]\s+\d{4})$|"
               r"^((Dec)\s+[1-31],\s+\d{4})$|"
               r"^((Dec)\s+[1-31]\s+\d{4})$")

subStr = r"\w\s\d{1,2}\s\d{4}"

print("----Part d tests that match (and should change):")
print(d.sub(subStr, "May 29, 2019"))

print("----Part d tests that match (and should remain unchanged):")
print(d.sub(subStr, "May 29 19"))

预期输出:

----Part d tests that match (and should change):
May 29 19
----Part d tests that match (and should remain unchanged):
May 29 19

实际输出(如果我将子字符串留空,以及目前的情况):

Blank:
----Part d tests that match (and should change):
May 29, 2019
----Part d tests that match (and should remain unchanged):
May 29 19

--------------------------------
Current:
----Part d tests that match (and should change):
    this = chr(ESCAPES[this][1])
KeyError: '\\w'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:/Users/Xavier/PycharmProjects/hw7/hw7.py", line 101, in <module>
    print(d.sub(subStr, "May 29, 2019"))
  File "C:\Users\Xavier\AppData\Local\Programs\Python\Python37\lib\re.py", line 309, in _subx
    template = _compile_repl(template, pattern)
  File "C:\Users\Xavier\AppData\Local\Programs\Python\Python37\lib\re.py", line 300, in _compile_repl
    return sre_parse.parse_template(repl, pattern)
  File "C:\Users\Xavier\AppData\Local\Programs\Python\Python37\lib\sre_parse.py", line 1024, in parse_template
    raise s.error('bad escape %s' % this, len(this))
re.error: bad escape \w at position 0

【问题讨论】:

  • 这些部分 [1-31] 不能这样工作,它是一个 character class 匹配 123 的范围从 1 到 3 和另一个 1 已经被 1 到 3 部分覆盖.您可能会查看 this page 以匹配日期格式。

标签: python regex string char digits


【解决方案1】:

如果不强制使用正则表达式,我会改为使用pandas.to_datetimetime.strptime

熊猫

import pandas as pd

s = "Jun 29, 2019"

try:
   print(pd.to_datetime(s).strftime('%d %b %Y'))

except ValueError:
   print('unrecognized time format!')

%b 表示月份的缩写,完整列表见the docs

时间

或者如果您没有安装 pandas,请使用内置库 time

import time

out = None
for pattern in ['%b %d, %Y', '%b %d %Y']:
    try:
        out = time.strftime('%d %b %Y', time.strptime(s, pattern))
    except ValueError:
        continue

if out is None:
    print('Error: Could not read the time')

正则表达式

如果您必须为此使用正则表达式,则需要替换 [1-31] 与例如(?:[12]\d|3[01]|\d),见regex tester

然后你错误地使用了re.sub。您可能希望在第一个大正则表达式中插入捕获组,然后在替换字符串中使用 \1, \2, ... 将它们放回原处,所以不要使用 \w

编辑

我能想到使用正则表达式和检查日期的唯一方法是

(?:(Jan|Mar|May|Jul|Aug|Oct|Dec) (3[01]|[12]\d|\d)|(Apr|Jun|Sep|Nov) (30|[12]\d|\d)|(Feb) (2[0-9]|[1]\d|\d)),? (\d{4})

并使用

subStr = '\1\3\5 \2\4\6 \7'

这非常丑陋,并且不处理闰年。

【讨论】:

    【解决方案2】:

    提示:

    • (Jan|Feb|Mar) 匹配并捕获月份...将其扩展到所有月份。
    • 方括号匹配单个字符...[1-31] 实际上是[123]...范围 1-3 或 1(冗余)。 [0-9] 或只是 \d 匹配任何单个数字。要求说日期不需要验证,所以\d{1,2}(匹配1或2位数)应该是合法的。
    • ? 用于 0 或 1 匹配,因此 ,? 是可选的逗号。
    • 4 位数年份,但仅捕获最后两位:\d{2}(\d{2})
    • 您应该在匹配字符串中包含三个捕获组。 \n 其中n 是组号插入捕获的内容,因此替换为r'\2 \1 \3'

    【讨论】:

      猜你喜欢
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-08
      • 2017-04-11
      • 2012-02-15
      相关资源
      最近更新 更多