如何用sed或Linux命令行工具交换前序日期早于后序的日期对位置?
用awk实现日期对的条件交换
当然可以实现!用awk来处理这个需求会比sed更顺手——因为它能直接处理日期的比较逻辑,不用写一堆绕人的正则。下面是具体的解决方案,完全满足你的需求:
核心脚本
awk '{ # 循环匹配行内所有的 "日期1=日期2" 格式 while (match($0, /([0-9]{4}\/[0-9]{2}\/[0-9]{2})=([0-9]{4}\/[0-9]{2}\/[0-9]{2})/, arr)) { # 将日期转换为 YYYYMMDD 的纯数字格式,方便直接比较大小 date1 = gensub(/\//, "", "g", arr[1]) date2 = gensub(/\//, "", "g", arr[2]) # 判断第一个日期是否早于第二个,是则交换位置,否则保留原格式 if (date1 < date2) { replace_str = arr[2] "=" arr[1] } else { replace_str = arr[0] } # 替换当前行中匹配到的日期对 $0 = substr($0, 1, RSTART-1) replace_str substr($0, RSTART+RLENGTH) } # 输出处理后的行 print $0 }' your_file.txt
脚本解释
- 匹配日期对:
match()函数会在每行中查找所有YYYY/MM/DD=YYYY/MM/DD格式的字符串,把第一个日期存在arr[1],第二个日期存在arr[2],整个匹配串存在arr[0]。 - 日期格式转换:用
gensub()去掉日期中的斜杠,转成纯数字(比如2017/04/22变成20170422),这样直接比较数字大小就能判断日期先后。 - 条件交换:如果第一个日期的数字值小于第二个(说明更早),就生成交换后的
日期2=日期1;否则保留原有的日期对格式。 - 循环替换:因为一行里可能有多个日期对,所以用
while循环处理,直到行内没有符合格式的日期对为止。
示例效果
假设你的输入行是:
2017/07/21=2017/05/23 some text somethign somthig 2017/04/22=2017/05/23 text2 smt1 smt2
处理后会输出:
2017/07/21=2017/05/23 some text somethign somthig 2017/05/23=2017/04/22 text2 smt1 smt2
(注:第一个日期对中2017/07/21晚于2017/05/23,所以不交换;第二个日期对中2017/04/22早于2017/05/23,所以执行交换)
关于sed的补充
如果一定要用sed实现,会非常繁琐——因为sed没有内置的日期比较能力,需要把年、月、日分别拆分出来做多层判断,正则表达式会极其复杂,出错概率高。所以更推荐用上面的awk方案,简洁且可靠。
内容的提问来源于stack exchange,提问作者Marko
相关产品推荐
相关产品推荐

