我在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
如何解决这个问题?
答案 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
,然后致电pipe
致getline
(你'重新使用不安全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)