多格式日期匹配Regex未捕获全部场景的问题求助
日期正则捕获与修正方案
核心思路
不拆分正则,通过调整匹配优先级和添加边界排除条件解决两个问题:
- 把单独年份的匹配规则放在最前端,同时排除它作为时间范围前缀的情况;
- 用
re.search()确保只捕获每行首个日期,配合replace(count=1)只替换一次。
修正后的正则与代码
import re def replace_dates(line, default_year=2000): # 正则规则:按匹配优先级排序,优先捕获单独年份,排除时间范围 date_pattern = re.compile( r'^.*?(?<!\d)(\d{4})(?!-\d{4})|' # 单独年份,排除后面跟"-xxxx"的情况 r'(\d{4}-\d{1,2})|' # YYYY-MM格式 r'(\d{4}-\d{1,2}-\d{1,2})|' # YYYY-MM-DD格式 r'(\d{1,2}-\d{1,2})|' # MM-DD(无年份) r'(\d{1,2}/\d{1,2})|' # MM/DD(无年份) r'(\d{4}/\d{1,2})|' # YYYY/MM格式 r'(\d{4}/\d{1,2}/\d{1,2})', # YYYY/MM/DD格式 re.IGNORECASE ) match = date_pattern.search(line) if not match: return line # 根据匹配组转换格式,仅替换首个匹配 if match.group(1): # 单独年份,保持YYYY格式 return line.replace(match.group(1), match.group(1), 1) elif match.group(2): # YYYY-MM格式直接保留 return line.replace(match.group(2), match.group(2), 1) elif match.group(3): # YYYY-MM-DD格式直接保留 return line.replace(match.group(3), match.group(3), 1) elif match.group(4): # MM-DD补全年份为YYYY-MM-DD formatted = f"{default_year}-{match.group(4)}" return line.replace(match.group(4), formatted, 1) elif match.group(5): # MM/DD转换为YYYY-MM-DD mm, dd = match.group(5).split('/') formatted = f"{default_year}-{mm.zfill(2)}-{dd.zfill(2)}" return line.replace(match.group(5), formatted, 1) elif match.group(6): # YYYY/MM转换为YYYY-MM yyyy, mm = match.group(6).split('/') formatted = f"{yyyy}-{mm.zfill(2)}" return line.replace(match.group(6), formatted, 1) elif match.group(7): # YYYY/MM/DD转换为YYYY-MM-DD yyyy, mm, dd = match.group(7).split('/') formatted = f"{yyyy}-{mm.zfill(2)}-{dd.zfill(2)}" return line.replace(match.group(7), formatted, 1)
关键细节说明
- 单独年份捕获:
(?<!\d)确保年份前无数字(避免被长数字串中的年份误匹配),(?!-\d{4})排除时间范围(如1786-1790中的1786不会被识别为单独年份); - 首个日期处理:
^.*?匹配行首到首个日期的前置内容,re.search()找到第一个匹配后,replace(count=1)只替换该行第一个日期; - 扩展性:如果有其他时间范围格式(如
1786~1790),只需在单独年份的否定前瞻中添加(?!~\d{4})即可扩展排除规则。
内容的提问来源于stack exchange,提问作者OnceUponATime
相关产品推荐
相关产品推荐

