【问题标题】:awk command to convert date format in a fileawk 命令转换文件中的日期格式
【发布时间】:2016-07-08 09:06:07
【问题描述】:

下面给出的是文件内容和使用的 awk 命令:

输入文件:in_t.txt

1,ABC,SSS,20-OCT-16,4,1,0,5,0,0,0,0
2,DEF,AAA,20-JUL-16,4,1,0,5,0,0,0,0

预期的输出文件:

SSS|2016-10-20,5
AAA|2016-07-20,5

我尝试了以下命令:

awk -F , '{print $3"|"$(date -d 4)","$8}' in_t.txt

得到的输出文件为:

SSS|20-OCT-16,5
AAA|20-JUL-16,5

我只想知道如何使用相同的 awk 命令格式化日期。尝试过

awk -F , '{print $3"|"$(date -d 4)","$8 +%Y-%m-%d}' in_t.txt

出现语法错误。可以请我帮忙吗?

【问题讨论】:

  • awk 中执行此操作。这可能比为每一行调用date 更有效。
  • 但是我该怎么做呢?我想格式化日期,但同样不起作用。
  • 使用split对输入的日期进行分割,然后将月份名称转换为数字
  • $(date -d 4) 没有调用date 命令,也没有在 awk 程序之外做任何事情。正如您在输出中看到的那样,它只是将两个空字符串与“4”连接起来,并使用$ 获取第 4 个字段的值。
  • You've asked 40 questions on this forum so far。为什么你现在跑来跑去在多个答案下发布相同的评论,甚至没有一个在你的评论中提供代码,并且在这个包含新问题的 5 年老问题下,而不是简单地问你的第 41 个问题?这比平常的chameleon questions还要糟糕!如果您有后续问题要问,只需发布​​一个问题,如果有用,请参考您现有的问题

标签: shell awk


【解决方案1】:

最好在 shell 本身中执行此操作并使用 date -d 转换 date 格式:

#!/bin/bash

while IFS=',' read -ra arr; do
   printf "%s|%s,%s\n" "${arr[2]}" $(date -d "${arr[3]}" '+%Y-%m-%d') "${arr[7]}"
done < file

SSS|2016-10-20,5
AAA|2016-07-20,5

【讨论】:

  • awk -F, '{打印 | "日期 -d "$4" \"+%Y-%m-%d\","$1","$8}' in_t.txt。得到这个解决方案的工作。我想了解这方面的更多细节。添加什么 |里面的印刷品是什么意思?还有$1和$8,怎么在date命令前加?
  • | 只是输出中SSS 之后的分隔符。由于我没有在此处提供 awk 答案,因此无法在此答案中解释这一点。
【解决方案2】:

您对单个命令的定义是什么?对 awk 的调用是单个 shell 命令。这可能是你想要的:

$ awk -F'[,-]' '{ printf "%s|20%02d-%02d-%02d,%s\n", $3, $6, (match("JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC",$5)+2)/3, $4, $10 }' file
SSS|2016-10-20,5
AAA|2016-07-20,5

顺便说一句,请务必记住 awk 不是 shell。您不能直接从 awk 调用 shell 工具(例如 date),而不是从 C 中调用。当您编写 $(date -d 4) 时,awk 看到一个未设置的变量,名为 date(数值 0),您从中提取名为d(也称为0)的未设置变量的值以获取数字结果0,然后将其与数字4连接以获取04,然后应用$运算符以获取字段$04 (=$4) 的内容。输出与shell命令date无关。

【讨论】:

  • 我无法决定是 +1 还是 -1 那个漂亮的讨厌的小 match() hack...
  • 是的,不幸的是 match() 事情是常见的 awk 习惯用法......
  • 这帮助我解决了我的问题,感谢@EdMorton
  • awk -F, '{打印 | "日期 -d "$4" \"+%Y-%m-%d\","$1","$8}' in_t.txt。得到这个解决方案的工作。我想了解这方面的更多细节。添加什么 |里面的印刷品是什么意思?还有$1和$8,怎么在date命令前加?
【解决方案3】:

来自Unix.com

稍微调整一下以满足您的需求

awk -v var="20-OCT-16" '
BEGIN{
  split("JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC", month, " ")
  for (i=1; i<=12; i++) mdigit[month[i]]=i
  m=toupper(substr(var,4,3))
  dat="20"substr(var,8,2)"-"sprintf("%02d",mdigit[m])"-"substr(var,1,2) 
  print dat
}'


2016-10-20

说明:

Prefix 20 {20}
Substring from 8th position to 2 positions {16}
Print - {-}
Check for the month literal (converting into uppercase) and assign numbers (mdigit) {10}
Print - {-}
Substring from 1st position to 2 positions {20}

【讨论】:

    【解决方案4】:

    这也可能对你有用。

    awk -F , 'BEGIN {months = "  JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"}
        { num = index(months, substr($4,4,3)) / 3
        if (length(num) == 1) {num = "0" num}
        date = "20" substr($4,8,2) "-" num "-" substr($4,1,2)
        print $3"|" date "," $8}' in_t.txt
    

    【讨论】:

      【解决方案5】:

      您与date 的通话很接近。您确实可以将它与getline 一起使用来解析和输出日期值:

      awk -F',' '{
      parsedate="date --date="$2" +%Y-%m-%d"
      parsedate | getline mydate
      close(parsedate)
      print $3"|"mydate","$8
      }'
      

      解释:

      • -F',' 将字段分隔符(分隔符)设置为逗号
      • parsedate="date --date="$2" +%Y-%m-%d" 利用dateability 将第二个字段转换为给定的输出格式,并将该命令分配给变量“parsedate”
      • parsedate | getline mydate 运行您的自定义“parsedate”命令,并将输出分配给 mydate 变量
      • close (parsedate) 可防止多行输入/输出出现某些错误(请参阅 Running a system command in AWK 以了解 getlineclose() 的讨论)
      • print $3"|"mydate","$8 输出由管道和逗号分隔的原始行的内容,并用新的“mydate”值替换字段 2。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-02
        • 1970-01-01
        • 2015-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多