简体   繁体   English

在AWK`rec = rec”中,“ $ i”无法按预期工作,其中$ i是记录中的每个字段

[英]In AWK `rec=rec“,”$i` doesn't work as expected, where $i is each field in a record

I've my vmstat output on a linux box as such: 我将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

I intend to keep the value under each field in a comma separated format along with timestamp(of course to use it as CSV file to be later transferred to our very loving MS Excel). 我打算将每个字段下的值与时间戳一起保留在逗号分隔的格式中(当然,将其用作CSV文件,以后再传输到我们非常喜欢的MS Excel中)。 So basically this is what I want: 所以基本上这就是我想要的:

Expected Output: 预期产量:

2016,05,19,23,53,58,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0,0

Script: 脚本:

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;}}'

Output that I get from my script: 我从脚本获得的输出:

2016,05,19,23,53,58 ,1,0,0,2675664,653028,3489156,0,0,1,19,22,7,5,1,94,0

Note the extra space : 58 ,1 and the last 0 missing from Expected Output. 请注意额外的空间: 58 ,1和预期输出中缺少最后一个0 I know the part in my script that is messing up is: rec=rec","$i 我知道脚本中混乱的部分是: rec=rec","$i

How to get around this ? 如何解决这个问题?

no need to reinvent awk features 无需重新设计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

The extra space in 58 ,1 is because you're telling awk to print a space (OFS) between dt (which ends in 58 ) and rec (which starts with ,1 ) with the comma in print dt,rec , nothing to do with rec=rec","$i . 在额外的空间58 ,1是因为你告诉AWK打印空间(OFS)DT之间(在此结束58 )和REC(其中开头,1用逗号) print dt,rec ,无关使用rec=rec","$i

The missing last field is because you're telling awk to stop looping before the last field. 缺少最后一个字段是因为您要告诉awk在最后一个字段之前停止循环。 Changing while (i < NF) to while (i <= NF) would have fixed that but the loop's not necessary at all (see below). while (i < NF)更改为while (i <= NF)可以解决此问题,但根本不需要循环(请参见下文)。

I'm assuming you don't have GNU awk or you'd be using strftime() instead of date . 我假设您没有GNU awk,或者您将使用strftime()代替date

Don't have shell call awk to call shell to call date and then a pipe to getline (which you're using unsafely btw, see http://awk.freeshell.org/AllAboutGetline ): 不要让shell调用awk来调用shell来调用date ,然后再使用pipe来获取getline (您正在不安全地使用btw,请参阅http://awk.freeshell.org/AllAboutGetline ):

awk 'BEGIN{"date +'%Y,%m,%d,%H,%M,%S'"| getline dt;} {script}'

Just have shell call date : 只需具有shell调用date

awk -v dt=$(date +'%Y,%m,%d,%H,%M,%S') '{script}'

and after getting rid of the UUOC the full script is simply: 摆脱了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

i <= NF will take care of the missing trailing 0. i <= NF将处理丢失的尾随0。

Instead of looping over the fields, a more awk'ish way of doing the same thing is to set OFS - Output Field Separator to ",". 而不是遍历这些字段,执行相同操作的一种更奇怪的方法是将OFS-输出字段分隔符设置为“,”。

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

One small glitch with that is that awk doesn't reformat $0 until something is changed. 其中的一个小故障是awk在更改某些内容之前不会重新格式化$ 0。 Setting $1=$1 is enough to force awk to do that ( setting the output field separator in awk ) 设置$ 1 = $ 1足以迫使awk做到这一点( 在awk中设置输出字段分隔符

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM