Windows批处理:为何部分findstr日期验证正则表达式失效
Windows命令行中的findstr工具使用非标准正则表达式语法,它不支持{n}这类限定重复次数的量词(比如{2}、{4})。而你在Regex101中使用的是PCRE(Perl兼容正则表达式),这类语法在PCRE中有效,但在findstr中会被当作普通字符处理(即{、2等字符会被要求在目标字符串中存在),这就是你的正则在Regex101中能匹配,但在findstr中失效的核心原因。
具体案例分析
第一个正则的侥幸匹配
你的第一个正则前面的^[mtwtfsMTWTFS][ouehra][nedurt]已经匹配了星期前缀(比如Mon),后面的(3[01]|[12][0-9]|0?[1-9])(\/|-)(1[0-2]|0?[1-9])\2也正确匹配了日期的日、分隔符、月部分(比如03/11/)。最后的([0-9]{2})?[0-9]{2}$部分虽然包含无效的{2}写法,但findstr处理时会将{2}视为普通字符,再加上^和$在findstr中的匹配逻辑存在一定宽松性,导致整个正则侥幸匹配成功,但这部分写法本质上不符合findstr语法规范。第二个正则失效的直接原因
第二个正则^(3[01]|[12][0-9]|0?[1-9])(\/|-)(1[0-2]|0?[1-9])\2([0-9]{2})?[0-9]{2}$中,([0-9]{2})?[0-9]{2}要求匹配“数字+{2}”的组合,但目标字符串03/11/2024中没有{字符,因此这部分无法匹配,导致整个正则匹配失败。重写正则的失效原因
你重写的正则^(0[1-9]|1[0-2])(\/)(0[1-9]|[1-2][0-9]|3[0-1])(\/)(2[0-9][0-9]{2})$中,[0-9]{2}同样是findstr不支持的语法,无法匹配年份的后两位,导致正则失效。
符合findstr语法的修正方案
将正则中的{n}替换为重复的字符类,比如:
- 把
[0-9]{2}替换为[0-9][0-9] - 把
[0-9]{4}替换为[0-9][0-9][0-9][0-9]
修正后的第二个正则示例:
set passed_date=03/11/2024 echo %passed_date%|findstr /r "^(3[01]|[12][0-9]|0?[1-9])(\/|-)(1[0-2]|0?[1-9])\2[0-9][0-9][0-9][0-9]$"
修正后的重写正则示例:
echo %passed_date%|findstr /r "^(0[1-9]|1[0-2])(\/)(0[1-9]|[1-2][0-9]|3[0-1])(\/)2[0-9][0-9][0-9]$"
内容的提问来源于stack exchange,提问作者Elk

