在 AWK `rec=rec","$i` 中没有按预期工作,其中 $i 是记录中的每个字段
In AWK `rec=rec","$i` doesn't work as expected, where $i is each field in a record
我的 vmstat
输出在 linux 框上,如下所示:
# cat vmstat.out
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 2675664 653028 3489156 0 0 1 19 22 7 5 1 94 0 0
我打算以逗号分隔的格式保留每个字段下的值以及时间戳(当然是将其用作 CSV 文件,以便稍后传输到我们非常喜欢的 MS Excel)。所以基本上这就是我想要的:
预期输出:
2016,05,19,23,53,58,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0,0
脚本:
cat vmstat.out | awk 'BEGIN{"date +'%Y,%m,%d,%H,%M,%S'"| getline dt;}{if (NR> 2) {i=1;while (i < NF) {rec=rec","$i; i++;} print dt,rec;}}'
我从我的脚本中得到的输出:
2016,05,19,23,53,58 ,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0
请注意预期输出中缺少的额外 space : 58 ,1
和最后一个 0
。我知道我的脚本中出现问题的部分是:rec=rec","$i
如何解决这个问题?
无需重新发明 awk
功能
$ awk -v OFS=, 'BEGIN{time=strftime("%Y,%m,%d,%H,%M,%S")}
NR>2{=; print time,[=10=]}' file
2016,05,19,15,12,29,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0,0
i <= NF 将处理丢失的尾随 0。
不是在字段上循环,做同样事情的一种更奇怪的方法是将 OFS - 输出字段分隔符设置为“,”。
awk '
BEGIN{OFS="," ; "date +'%Y,%m,%d,%H,%M,%S'"| getline dt;}
{if (NR> 2) {= ; print dt,[=10=];}}
' vmstat.out
其中的一个小故障是 awk 在更改内容之前不会重新格式化 $0。设置 $1=$1 足以强制 awk 这样做 (setting the output field separator in awk)
58 ,1
中额外的 space 是因为你告诉 awk 在 dt(以 58
结尾)和 rec 之间打印一个 space (OFS) (以 ,1
开头)与 print dt,rec
中的逗号,与 rec=rec","$i
.
无关
缺少最后一个字段是因为您告诉 awk 在最后一个字段之前停止循环。将 while (i < NF)
更改为 while (i <= NF)
会解决这个问题,但根本不需要循环(见下文)。
我假设您没有 GNU awk,或者您将使用 strftime()
而不是 date
。
没有shell
调用awk
调用shell
调用date
然后pipe
调用getline
(这顺便说一句,你使用的不安全,请参阅 http://awk.freeshell.org/AllAboutGetline):
awk 'BEGIN{"date +'%Y,%m,%d,%H,%M,%S'"| getline dt;} {script}'
只需 shell
调用 date
:
awk -v dt=$(date +'%Y,%m,%d,%H,%M,%S') '{script}'
在去掉 UUOC 之后,完整的脚本就是:
$ awk -v dt=$(date +'%Y,%m,%d,%H,%M,%S') -v OFS=, 'NR>2{=dt OFS ; print}' vmstat.out
2016,05,19,14,53,05,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0,0
我的 vmstat
输出在 linux 框上,如下所示:
# cat vmstat.out
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 2675664 653028 3489156 0 0 1 19 22 7 5 1 94 0 0
我打算以逗号分隔的格式保留每个字段下的值以及时间戳(当然是将其用作 CSV 文件,以便稍后传输到我们非常喜欢的 MS Excel)。所以基本上这就是我想要的:
预期输出:
2016,05,19,23,53,58,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0,0
脚本:
cat vmstat.out | awk 'BEGIN{"date +'%Y,%m,%d,%H,%M,%S'"| getline dt;}{if (NR> 2) {i=1;while (i < NF) {rec=rec","$i; i++;} print dt,rec;}}'
我从我的脚本中得到的输出:
2016,05,19,23,53,58 ,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0
请注意预期输出中缺少的额外 space : 58 ,1
和最后一个 0
。我知道我的脚本中出现问题的部分是:rec=rec","$i
如何解决这个问题?
无需重新发明 awk
功能
$ awk -v OFS=, 'BEGIN{time=strftime("%Y,%m,%d,%H,%M,%S")}
NR>2{=; print time,[=10=]}' file
2016,05,19,15,12,29,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0,0
i <= NF 将处理丢失的尾随 0。
不是在字段上循环,做同样事情的一种更奇怪的方法是将 OFS - 输出字段分隔符设置为“,”。
awk '
BEGIN{OFS="," ; "date +'%Y,%m,%d,%H,%M,%S'"| getline dt;}
{if (NR> 2) {= ; print dt,[=10=];}}
' vmstat.out
其中的一个小故障是 awk 在更改内容之前不会重新格式化 $0。设置 $1=$1 足以强制 awk 这样做 (setting the output field separator in awk)
58 ,1
中额外的 space 是因为你告诉 awk 在 dt(以 58
结尾)和 rec 之间打印一个 space (OFS) (以 ,1
开头)与 print dt,rec
中的逗号,与 rec=rec","$i
.
缺少最后一个字段是因为您告诉 awk 在最后一个字段之前停止循环。将 while (i < NF)
更改为 while (i <= NF)
会解决这个问题,但根本不需要循环(见下文)。
我假设您没有 GNU awk,或者您将使用 strftime()
而不是 date
。
没有shell
调用awk
调用shell
调用date
然后pipe
调用getline
(这顺便说一句,你使用的不安全,请参阅 http://awk.freeshell.org/AllAboutGetline):
awk 'BEGIN{"date +'%Y,%m,%d,%H,%M,%S'"| getline dt;} {script}'
只需 shell
调用 date
:
awk -v dt=$(date +'%Y,%m,%d,%H,%M,%S') '{script}'
在去掉 UUOC 之后,完整的脚本就是:
$ awk -v dt=$(date +'%Y,%m,%d,%H,%M,%S') -v OFS=, 'NR>2{=dt OFS ; print}' vmstat.out
2016,05,19,14,53,05,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0,0