正则表达式更改日期字符串

时间:2019-05-31 07:02:07

标签: python regex string char digits

我是python的新手,对于此作业,我们被要求使用单个正则表达式来解决每个提示。我已经完成了提示A-C,但是现在我被提示D困住了。 这是提示:

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

要匹配的有效日期格式包含以下元素: •月份必须是常见的三个字母的月份缩写,以大写字母开头,后跟两个小写字母:1月,2月,3月,4月,5月,6月,7月,8月,9月,10月,11月,12月。
•日期可能是一两位数字。不必检查有效的日期,可以接受带有前导零的日期,例如03。 •年份正好是四位数。
•月份和日期由一个或多个空格分隔。日期和年份也用一个或多个空格分隔,但允许在日期之后立即使用逗号(日期和逗号之间不允许有空格)

我遇到的困难:我不确定在r“ ...”语句中输入什么(请参阅代码),现在我得到的错误是“ re.error:逃逸错误\ 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

2 个答案:

答案 0 :(得分:0)

提示:

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

答案 1 :(得分:0)

如果不是必须使用正则表达式,我会改用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

时间

或者如果您没有安装熊猫,请使用内置库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')

regex

如果您必须为此使用正则表达式,则需要替换[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'

这太丑陋了,不治疗treat年。