Awk匹配YYYY-MM-DD日期列:为何某正则命令失效?
为什么两条awk日期匹配命令效果不同?
这个问题的核心在于awk默认使用的正则表达式语法规则,咱们一步步拆解差异:
能正常工作的命令分析
这条命令用的是最基础的正则写法:
echo 1,2,3,4,2015-12-34 | awk -F, '{if($5~/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$/) print $1}'
它通过重复写[0-9]来明确匹配“4位数字-2位数字-2位数字”的格式,这种写法不管是在POSIX基本正则表达式(BRE)还是扩展正则表达式(ERE)里都能被正确识别,所以可以正常匹配目标日期列。
无法工作的命令问题所在
这条命令用了更简洁的量词语法,但踩了awk正则的默认规则坑:
echo 1,2,3,4,2015-12-34 | awk -F, '{if($5~/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)print $1}'
awk默认使用POSIX基本正则表达式(BRE),在BRE语法里,{}是普通的字面字符,不会被当成“重复n次”的量词来解析。也就是说,这条命令里的{4}和{2}会被当成要匹配的字符本身,而不是“前面的字符重复4次/2次”,自然就匹配不到你的日期格式了。
两种解决方法
方法1:转义量词(适配BRE规则)
把{}转义成\{},让BRE把它们识别为量词:
echo 1,2,3,4,2015-12-34 | awk -F, '{if($5~/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}$/)print $1}'
方法2:切换到扩展正则表达式(ERE)
如果想用更简洁的{n}写法,可以让awk使用ERE模式。不同awk版本的开启方式略有不同:
- GNU awk(gawk)可以用
-E选项:
echo 1,2,3,4,2015-12-34 | awk -E -F, '{if($5~/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)print $1}'
- 部分老版本awk可以用
--re-interval选项:
echo 1,2,3,4,2015-12-34 | awk --re-interval -F, '{if($5~/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/)print $1}'
内容的提问来源于stack exchange,提问作者ggupta
相关产品推荐
相关产品推荐

