正则表达式模式用于解析工作时间字符串

3
我正在编写一个Python库,用于解析不同的工作时间字符串并生成标准格式的小时数。我在以下情况卡住了:
我的正则表达式应该将Mon - Fri 7am - 5pm Sat 9am - 3pm分组为['Mon - Fri 7am - 5pm ', 'Sat 9am - 3pm'],但如果第一段和第二段之间有逗号,则应返回[]
此外,逗号可以放置在任何地方,但不能放在两个工作日和持续时间之间。例如:Mon - Fri 7am - 5pm Sat 9am - 3pm and available upon email, phone call 应该返回 ['Mon - Fri 7am - 5pm ', 'Sat 9am - 3pm']
这是我尝试过的内容:
import re
pattern = """(
    (?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|m|w|f|thurs) # Start weekday
\s*[-|to]+\s* # Seperator
(?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|^(?![ap])m|w|f|thurs)?  # End weekday
\s*[from]*\s* # Seperator
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?) # Start hour
\s*[-|to]+\s* # Seperator
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?) # Close hour
)"""

regEx = re.compile(pattern, re.IGNORECASE|re.VERBOSE)

print re.findall(regEx, "Mon - Fri 7am - 5pm Sat 9am - 3pm")
# output ['Mon - Fri 7am - 5pm ', 'Sat 9am - 3pm']
print re.findall(regEx, "Mon - Fri 7am - 5pm Sat - Sun 9am - 3pm")
# output ['Mon - Fri 7am - 5pm ', 'Sat - Sun 9am - 3pm']
print re.findall(regEx, "Mon - Fri 7am - 5pm, Sat 9am - 3pm")
# expected output []
# but I get ['Mon - Fri 7am - 5pm,', 'Sat 9am - 3pm']
print re.findall(regEx, "Mon - Fri 7am - 5pm , Sat 9am - 3pm")
# expected output []
# but I get ['Mon - Fri 7am - 5pm ', 'Sat 9am - 3pm']

我也尝试在我的正则表达式中使用了负向先行断言模式

pattern = """(
(?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|m|w|f|thurs)
\s*[-|to]+\s*
(?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|^(?![ap])m|w|f|thurs)?
\s*[from]*\s*
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?)
\s*[-|to]+\s*
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?)
(?![^,])
)"""

但是我没有得到预期的结果。我应该显式编写检查条件的代码吗?有没有仅仅修改正则表达式而不需要编写显式条件检查的方法?

另一种我喜欢的实现方式是,在两个工作日持续时间之间插入逗号(如果不存在逗号),然后将我的正则表达式更改为逗号分组/拆分。"Mon - Fri 7am - 5pm Sat 9am - 3pm" => "Mon - Fri 7am - 5pm, Sat 9am - 3pm"


把逗号去掉怎么样?这样不是更简单吗?在发送到 re 之前过滤掉逗号。 - CppLearner
我需要逗号以便进行进一步处理,所以我想在两个星期时间段之间添加逗号,例如:"Mon - Fri 7am - 5pm Sat 9am - 3pm"。我现在会编辑我的问题。"further processing" - 如果存在逗号,我已经有一个解析器来标准化字符串。 - Garfield
3个回答

1

我认为你可以通过匹配整个表达式来实现它,这样逗号(和其他字符)就不允许出现:

pattern = """^(
(
    (?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|m|w|f|thurs) # Start weekday
\s*[-|to]+\s* # Seperator
(?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|^(?![ap])m|w|f|thurs)?  # End weekday
\s*[from]*\s* # Seperator
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?) # Start hour
\s*[-|to]+\s* # Seperator
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?) # Close hour
)
)+$""

这将输出:
[('Sat 9am - 3pm', 'Sat 9am - 3pm')]
[('Sat - Sun 9am - 3pm', 'Sat - Sun 9am - 3pm')]
[]
[]

希望有所帮助。

你注意到数组中的两个项目了吗? - Garfield
是的,我正在尝试找到更好的解决方案 :) (实际上,我无法弄清楚为什么当您删除第一个括号时它不起作用...) - Y__

0

我无法想出如何在一个正则表达式中完成这个任务,你的问题很难。 我可以做到你所需的,但请注意我不以此为豪。

假设你有一个函数来实现这个...

def sample_funct(unparsed_schedule)
    result = []

    # Day Pattern
    pattern = """
    (?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|m|w|f|thurs) # Start weekday
    \s*[-|to]+\s* # Seperator
    (?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|^(?![ap])m|w|f|thurs)?  # End weekday
    \s*[from]*\s* # Seperator
    (?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][\.]?m\.?) # Start hour
    \s*[-|to]+\s* # Seperator
    (?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][\.]?m\.?) # Close hour
    """

    # No commas pattern
    pattern2 = "%s\s*[^,]\s*%s" % (pattern, pattern)

    # Actual Regex Pattern Items
    schedule     = re.compile(pattern, re.IGNORECASE|re.VERBOSE)
    remove_comma = re.compile(pattern2, re.IGNORECASE|re.VERBOSE)

    # Check we have no commas in the middle
    valid_result = re.search(remove_comma, unparsed_schedule)
    if valid_result:
        # Positive result, return the list with schedules
        result = re.findall(schedule, validresult.group(0))

    # If no valid results will return empty list
    return result 

谢谢!我将字符串转换为唯一格式,即为没有逗号的部分插入了逗号。 - Garfield

0
我写了几行代码来检查并在每个工作日持续时间之间不存在逗号时插入逗号。因此,我能够获得相同的格式“周一至周五早上7点至下午5点,周六上午9点至下午3点”,以便我可以继续进行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接