【问题标题】:Unix command to replace old date with current date dynamicallyUnix命令用当前日期动态替换旧日期
【发布时间】:2017-03-03 03:07:42
【问题描述】:

我正在尝试处理一个脚本,它有一个与日期和一些字符串连接的列。我想对日期部分进行子串化并与今天的日期进行比较。如果它比今天早,我想用今天的日期替换。这是一个例子。

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

我希望通过更改第 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

【问题讨论】:

  • 所以,假设今天的日期是 2016-10-20,如果数据的日期部分对应的日期早于 2016-10-20,您希望将日期替换为 2016-10 -20,但如果是 2016 年或 2017 年或以后的未来日期,不要管它?日期可能是 2015 年或更早?日期字段后面的字母是否总是 O 就像您的示例一样?
  • 我试图挽救格式并删除示例中每一行之间的空行。我想星号实际上也不是数据的一部分。请您查看一下,edit您的问题需要澄清吗?
  • 从其他数据中分离日期似乎是一种提高自己理智和简化进一步下游处理的方法。
  • @tripleee:我没有留下数据,因为** 用于突出显示已更改的部分。否:我确定您现在展示的 ** 是标记,而不是原始数据的一部分。
  • 感谢@triplee 格式化。星号不是数据的一部分。

标签: shell unix awk sed


【解决方案1】:

如果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-&gt;ymd("")} 将今天的日期保存在 $d 变量中,仅在脚本开始时执行此操作
  • s/.* \K\d+/$&amp; &lt; $d ? $d : $&amp;/e提取要替换的日期,与$d比较,如果提取日期早于$d,则替换为$d

    • .* \K 匹配到行中的最后一个空格,通过使用\K,到此为止的匹配文本将被丢弃

    • $&amp; 包含来自\d+ 的匹配字符串

    • e 标志允许在替换部分使用代码 $&amp; &lt; $d ? $d : $&amp; 而不是字符串


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

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


延伸阅读:

【讨论】:

    【解决方案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
    

    【讨论】:

    • 我在 solaris 中使用它。看起来语法不接受
    • awk -v refdate="$(date +%Y%m%d)" '{ if ($5
    • 如果你在 Solaris 上,问题可能是$(…) 仍然不能被你使用的 shell 识别(/bin/sh 在 Solaris 上落后了几十年) .您可能需要使用:awk -v refdate=`date +%Y%m%d` '{ … }' test.txt。如果这不能解决问题,您需要查看 Solaris Awk 手册页并查看是否可以识别 substr。我认为用反引号代替$(…) 可能会解决问题,但如果还不够,还有更多调试方法。
    【解决方案3】:

    在 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
    

    【讨论】:

    • 在 Gnu awk 上?您是否尝试过更改 cmets(未在 Solaris 上测试)?
    • 我不确定如何在 solaris ksh 中更改这部分 sub(/^.{8}/, (b
    • 我也没有,但这对 original-awk 和 mawk 有效:sub(/^......../, (b&lt;a?a:b), $5)
    • GNU awk 具有日期/时间处理代码,不需要您使用 date
    • @JonathanLeffler 当然有,但使用 date 可以在我自闭症患者的眼睛中节省字节数。 :D
    【解决方案4】:

    我终于明白了!感谢詹姆斯、乔纳森和其他人。

    这是我在 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
    

    【讨论】:

    • /usr/xpg4/bin/awk -va=date +%Y%m%d '(b=substr($5,1,8)) && gsub(/^.{8}/,(b
    猜你喜欢
    • 2021-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    相关资源
    最近更新 更多