Unix命令动态地用当前日期替换旧日期

时间:2016-10-20 23:06:38

标签: shell unix awk sed

我正在尝试编写一个脚本,其中有一个与日期和一些字符串连接的列。我想将日期部分子字符串并与今天的日期进行比较。如果它比今天更旧,我想用今天的日期替换。这是一个例子。

cat test.txt
aaaa              RR  242       644126              20161030O00001.0000
bbbb              RR  242       644126              20161225O00001.0000
aaaa              RR  242       644126              20161012O00001.0000
aaaa              RR  242       644126              20170129O00001.0000
aaaa              RR  242       644126              20170326O00001.0000
aaaa              RR  242       644126              20170430O00001.0000
aaaa              RR  242       644126              20161015O00001.0000

我想通过更改colum5 - 第3行和第7行的日期戳来获得如下输出。请帮忙。如果可能的话,我正在寻找单一的命令来使它工作。

aaaa              RR  242       644126              20161030O00001.0000
bbbb              RR  242       644126              20161225O00001.0000
aaaa              RR  242       644126              20161020000001.0000
aaaa              RR  242       644126              20170129O00001.0000
aaaa              RR  242       644126              20170326O00001.0000
aaaa              RR  242       644126              20170430O00001.0000
aaaa              RR  242       644126              20161020000001.0000

4 个答案:

答案 0 :(得分:2)

使用普通的Awk,因此不假设内置日期支持:

awk -v refdate="$(date +%Y%m%d)" '{ if ($5 < refdate) $5 = refdate substr($5, 9); print}'

给出数据文件和当前日期2016-10-20:

aaaa RR 242 644126 20161030O00001.0000
bbbb RR 242 644126 20161225O00001.0000
aaaa RR 242 644126 20161012O00001.0000
aaaa RR 242 644126 20170129O00001.0000
aaaa RR 242 644126 20170326O00001.0000
aaaa RR 242 644126 20170430O00001.0000
aaaa RR 242 644126 20161015O00001.0000

输出结果为:

aaaa RR 242 644126 20161030O00001.0000
bbbb RR 242 644126 20161225O00001.0000
aaaa RR 242 644126 20161020O00001.0000
aaaa RR 242 644126 20170129O00001.0000
aaaa RR 242 644126 20170326O00001.0000
aaaa RR 242 644126 20170430O00001.0000
aaaa RR 242 644126 20161020O00001.0000

答案 1 :(得分:0)

如果perl没问题......注意:2016-10-21已经在我的世界里了;)


要使用Time::Piece模块获取今天的日期:

$ perl -MTime::Piece -le '$d = localtime->ymd(""); print $d'
20161021


样本输入:

$ cat ip.txt 
aaaa RR 242 644126 20161030O00001.0000
bbbb RR 242 644126 20161225O00001.0000
aaaa RR 242 644126 20161012O00001.0000
aaaa RR 242 644126 20170129O00001.0000
aaaa RR 242 644126 20170326O00001.0000
aaaa RR 242 644126 20170430O00001.0000
aaaa RR 242 644126 20161015O00001.0000

解决方案:

$ perl -MTime::Piece -pe 'BEGIN{$d=localtime->ymd("")} s/.* \K\d+/$& < $d ? $d : $&/e' ip.txt
aaaa RR 242 644126 20161030O00001.0000
bbbb RR 242 644126 20161225O00001.0000
aaaa RR 242 644126 20161021O00001.0000
aaaa RR 242 644126 20170129O00001.0000
aaaa RR 242 644126 20170326O00001.0000
aaaa RR 242 644126 20170430O00001.0000
aaaa RR 242 644126 20161021O00001.0000
  • BEGIN{$d=localtime->ymd("")}将今天的日期保存在$d变量中,仅在脚本开头执行此操作
  • s/.* \K\d+/$& < $d ? $d : $&/e提取要替换的日期,与$d进行比较,如果提取日期早于$d,则替换为$d

    • .* \K匹配到最后一个空格,使用\K,此时匹配的文字将被丢弃

    • $&包含来自\d+

    • 的匹配字符串
    • e标志允许在替换部分
    • 中使用代码$& < $d ? $d : $&而不是字符串


使用date命令代替Time::Piece模块:

perl -pe 'BEGIN{chomp($d=`date +%Y%m%d`)} s/.* \K\d+/$& < $d ? $d : $&/e' ip.txt


进一步阅读:

答案 2 :(得分:0)

在Gnu awk中(见解释中的最后评论):

$ awk -v a="$(date +%Y%m%d)" '(b=substr($5,1,8)) && sub(/^.{8}/,(b<a?a:b),$5)' file
aaaa RR 242 644126 20161030O00001.0000
bbbb RR 242 644126 20161225O00001.0000
aaaa RR 242 644126 20161021O00001.0000
aaaa RR 242 644126 20170129O00001.0000
aaaa RR 242 644126 20170326O00001.0000
aaaa RR 242 644126 20170430O00001.0000
aaaa RR 242 644126 20161021O00001.0000

说明:

awk -v a="$(date +%Y%m%d)"  # set the date to a var
'                           # '
(b = substr($5,1,8) ) &&    # read first 8 chars of 5th field to b var
sub(/^.{8}/, (b<a?a:b), $5) # replace 8 first chars with a if b is less than a
                            # to make it compatible with other awks, change
                            # /^.{8}/ to /^......../
' file

答案 3 :(得分:0)

我终于想通了!谢谢詹姆斯,乔纳森和其他人。

这是我在solaris的命令。

$cat test.txt
aaaa RR 242 644126 20161030O00001.0000
bbbb RR 242 644126 20161012O00001.0000
aaaa RR 242 644126 20161013O00001.0000
aaaa RR 242 644126 20170129O00001.0000
aaaa RR 242 644126 20170326O00001.0000
aaaa RR 242 644126 20170430O00001.0000
aaaa RR 242 644126 20161014O00001.0000

$ /usr/xpg4/bin/awk -v a=`date +%Y%m%d` '(b=substr($5,1,8)) && gsub(/^.{8}/,(b<a?a:b),$5)' test.txt    
aaaa RR 242 644126 20161030O00001.0000
bbbb RR 242 644126 20161022O00001.0000
aaaa RR 242 644126 20161022O00001.0000
aaaa RR 242 644126 20170129O00001.0000
aaaa RR 242 644126 20170326O00001.0000
aaaa RR 242 644126 20170430O00001.0000
aaaa RR 242 644126 20161022O00001.0000