在AWK`rec = rec"," $ i`没有按预期工作,其中$ i是记录中的每个字段

时间:2016-05-19 18:40:37

标签: linux bash awk gawk

我在Linux机箱上的vmstat输出是这样的:

# 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

请注意额外空格:58 ,1以及预期输出中缺少的最后一个0。我知道我脚本中的部分是搞乱的:rec=rec","$i

如何解决这个问题?

3 个答案:

答案 0 :(得分:3)

无需重新发明awk功能

$ awk -v OFS=, 'BEGIN{time=strftime("%Y,%m,%d,%H,%M,%S")} 
                 NR>2{$1=$1; print time,$0}' file

2016,05,19,15,12,29,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0,0

答案 1 :(得分:2)

58 ,1中的额外空格是因为你告诉awk在dt(以58结束)和rec(以,1开头)之间打印空格(OFS)使用print dt,rec中的逗号,与rec=rec","$i无关。

缺少的最后一个字段是因为你告诉awk在最后一个字段之前停止循环。将while (i < NF)更改为while (i <= NF)会修复此问题,但根本不需要循环(见下文)。

我假设你没有GNU awk,或者你使用的是strftime()而不是date

没有shell致电awk致电shell致电date,然后致电pipegetline(你'重新使用不安全btw,请参阅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{$1=dt OFS $1; 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

答案 2 :(得分:1)

i&lt; = NF将处理丢失的尾随0。

而不是在字段上循环,更好的做法是将OFS - 输出字段分隔符设置为&#34;,&#34;。

awk ' BEGIN{OFS="," ; "date +'%Y,%m,%d,%H,%M,%S'"| getline dt;} {if (NR> 2) {$1=$1 ; print dt,$0;}} ' vmstat.out

一个小故障就是awk在改变某些东西之前不会重新格式化$ 0。设置$ 1 = $ 1足以强制awk执行此操作(setting the output field separator in awk