如何使用sed将文本中日期转换为yyyy/mm/dd及yyyymmdd格式
日期格式转换实现方案
已知工具生成的expiration文件固定为单行格式:node_software_expiration_date 星期 月份缩写 日 时间 年,目标是将行内容转换为node_software_expiration_date yyyymmdd格式,也支持yyyy/mm/dd格式输出,可选择以下任意一种实现方式:
纯sed实现
sed本身无内置日期处理能力,需要手动做月份缩写到数字的映射,再拼接字段。
- 输出
yyyymmdd格式的命令:
sed -i -E ' s/ Jan / 01 / s/ Feb / 02 / s/ Mar / 03 / s/ Apr / 04 / s/ May / 05 / s/ Jun / 06 / s/ Jul / 07 / s/ Aug / 08 / s/ Sep / 09 / s/ Oct / 10 / s/ Nov / 11 / s/ Dec / 12 / s/^(\S+) \S+ (\S+) ([0-9]{2}) ([0-9]{1,2}) \S+ (\S+)$/\1 \5\3\4/ s/ ([0-9]{4})([0-9]{2})([0-9])$/ \1\20\3/ ' expiration
- 输出
yyyy/mm/dd格式的命令:
sed -i -E ' s/ Jan / 01 / s/ Feb / 02 / s/ Mar / 03 / s/ Apr / 04 / s/ May / 05 / s/ Jun / 06 / s/ Jul / 07 / s/ Aug / 08 / s/ Sep / 09 / s/ Oct / 10 / s/ Nov / 11 / s/ Dec / 12 / s/^(\S+) \S+ (\S+) ([0-9]{2}) ([0-9]{1,2}) \S+ (\S+)$/\1 \5\/\3\/\4/ s/ ([0-9]{4})\/([0-9]{2})\/([0-9])$/ \1\/\2\/0\3/ ' expiration
注:macOS系统自带的BSD sed需要将
-i参数改为-i '',否则会报错。
awk实现
awk按字段拆分处理逻辑更清晰,不需要写复杂正则,维护成本更低。
- 输出
yyyymmdd格式的命令:
awk ' BEGIN { m["Jan"]="01"; m["Feb"]="02"; m["Mar"]="03"; m["Apr"]="04" m["May"]="05"; m["Jun"]="06"; m["Jul"]="07"; m["Aug"]="08" m["Sep"]="09"; m["Oct"]="10"; m["Nov"]="11"; m["Dec"]="12" } { day = sprintf("%02d", $4) print $1, $6 m[$3] day } ' expiration > expiration.tmp && mv expiration.tmp expiration
- 输出
yyyy/mm/dd格式时,仅需将print $1, $6 m[$3] day替换为print $1, $6"/"m[$3]"/"day即可。
系统date命令实现
不需要手动维护月份映射,依靠系统date命令自带的日期解析能力做格式转换,容错性最高。
- GNU date(绝大多数Linux发行版默认):
read prefix dt < expiration new_dt=$(date -d "$dt" +%Y%m%d) echo "$prefix $new_dt" > expiration
- BSD date(macOS/FreeBSD系统默认):
read prefix wk mon day tm year < expiration new_dt=$(date -j -f "%a %b %d %H:%M:%S %Y" "$wk $mon $day $tm $year" +%Y%m%d) echo "$prefix $new_dt" > expiration
需要yyyy/mm/dd格式时,将date命令的+%Y%m%d参数替换为+%Y/%m/%d即可。
cron定时任务配置修正
原cron命令存在两个问题:sed未指定输入文件、未做日期格式转换,无法达到预期效果。推荐用awk方案配置cron,稳定性高且命令简洁:
./export_expiration && awk 'BEGIN{m["Jan"]="01";m["Feb"]="02";m["Mar"]="03";m["Apr"]="04";m["May"]="05";m["Jun"]="06";m["Jul"]="07";m["Aug"]="08";m["Sep"]="09";m["Oct"]="10";m["Nov"]="11";m["Dec"]="12"}{day=sprintf("%02d",$4);print $1,$6 m[$3] day}' expiration > expiration.tmp && mv expiration.tmp expiration
注意:禁止在同一条命令中直接用
> expiration写入原文件,会导致shell提前截断文件造成内容丢失,先写临时文件再原子替换是标准安全做法。
内容的提问来源于stack exchange,提问作者DizzyNYC
相关产品推荐
相关产品推荐

