使用其他命令修改awk参数



我有一个像这样的文件,它在行中包含多个字段。我想显示其中一些,同时用另一个命令处理其中一个。

TITLE,OpenVPN ...
HEADER,CLIENT_LIST,Common Name,Real Address,Virtual Address,Virtual IPv6 Address,Bytes Received,Bytes Sent,Connected Since,Connected Since (time_t),Username,Client ID,Peer ID
CLIENT_LIST,name1,1.1.1.1:1,10.0.0.1,,2692253,3765861,Wed Jun 23 12:51:08 2021,1624452668,name1,4727,0
CLIENT_LIST,name2,2.2.2.2:2,10.0.0.2,,1571221,2080242,Thu Jul  1 19:24:10 2021,1625167450,name2,5625,0
CLIENT_LIST,name3,3.3.3.3:3,10.0.0.3,,2670410,3736957,Wed Jun 23 16:20:51 2021,1624465251,name3,4747,0
...

预期输出为:

name1  10.0.0.1  2021-06-23 12:51:08
name2  10.0.0.2  2021-07-01 19:24:10
name3  10.0.0.3  2021-06-23 16:20:51

我现在的命令是:

grep '^CLIENT_LIST,' /var/run/ovpn-server.status |awk -F',' '{print $2 $4 $9}' |sort

它打印所需的字段,但不将时间戳转换为格式化的时间。这是命令:

date -d @1624452668 +"%Y-%m-%d %H:%M:%S"

如何将date命令集成到awk脚本中?或者还有什么其他解决方案可以实现这一点?

我还打算使用column命令将输出放入列/表布局中,我以前也这样做过,所以这不是问题的一部分。

您可以使用此awk:

awk -F, -v OFS='t' '$1 == "CLIENT_LIST" {
cmd = "date +47%Y-%m-%d %H:%M:%S47 -d47@" $9 "47"
print $2, $4, ((cmd | getline dt) > 0 ? dt : $9)
close(dt)
}' file
name1   10.0.0.1    2021-06-23 08:51:08
name2   10.0.0.2    2021-07-01 15:24:10
name3   10.0.0.3    2021-06-23 12:20:51

解释:

  • -F, -v OFS='t':将输入字段分隔符设置为,,将输出字段分隔符设为选项卡
  • '$1 == "CLIENT_LIST":当第一个字段为CLIENT_LIST时执行
  • cmd = "date +47%Y-%m-%d %H:%M:%S47 -d47@" $9 "47":使用$9格式化date命令
  • cmd | getline dt调用外部date命令
  • (cmd | getline dt) > 0:当date命令成功时
  • print:打印date字段的第2个、第4个和输出

如果您实际上只想重新格式化$8中的日期+时间,而不是将从$9开始的时间转换为日期+时间的秒数,那么您可以执行以下操作,这将比调用date快几个数量级,因为这将要求awk在每个输入行生成一个子shell,以便从该子shell调用date,这将非常困难缓慢的

在每个Unix盒子上的任何shell中使用任何awk:

$ cat tst.awk
BEGIN { FS=","; OFS="t" }
NR > 2 {
split($8,t," ")
mthNr = (index("JanFebMarAprMayJunJulAugSepOctNovDec",t[2])+2)/3
print $2, $4, sprintf("%04d-%02d-%02d %s", t[5], mthNr, t[3], t[4])
}

$ awk -f tst.awk file
name1   10.0.0.1        2021-06-23 12:51:08
name2   10.0.0.2        2021-07-01 19:24:10
name3   10.0.0.3        2021-06-23 16:20:51

或者,如果你真的想从$9开始使用epoch秒,那么对strftime()使用GNU awk,这样你就不必生成子shell来调用date(但请注意,输出现在变得依赖于TZ,就像date一样(:

$ cat tst.awk
BEGIN { FS=","; OFS="t" }
NR > 2 {
print $2, $4, strftime("%F %T",$9)
}

$ awk -f tst.awk file
name1   10.0.0.1        2021-06-23 07:51:08
name2   10.0.0.2        2021-07-01 14:24:10
name3   10.0.0.3        2021-06-23 11:20:51

$ TZ=UTC awk -f tst.awk file
name1   10.0.0.1        2021-06-23 12:51:08
name2   10.0.0.2        2021-07-01 19:24:10
name3   10.0.0.3        2021-06-23 16:20:51

或者在strftime((中设置UTC标志(如果UTC是您数据中的UTC(:

$ cat tst.awk
BEGIN { FS=","; OFS="t" }
NR > 2 {
print $2, $4, strftime("%F %T",$9,1)
}

$ awk -f tst.awk file
name1   10.0.0.1        2021-06-23 12:51:08
name2   10.0.0.2        2021-07-01 19:24:10
name3   10.0.0.3        2021-06-23 16:20:51

最新更新