删除最后一个字符并使用 awk 将该值乘以一个数字
remove the last character and multiply the value with a number using awk
我正在使用 dstat 工具获取 eth0 接口的网络使用情况。
dstat 给出如下输出:
----total-cpu-usage---- -dsk/total- --net/eth0- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
3 2 95 1 0 0|4035B 143k| 0 0 | 0 0 |1539 2511
3 3 94 0 0 0| 0 24k|3924B 7549B| 0 0 |1821 2851
3 3 94 0 0 0| 0 84k|3766B 2648B| 0 0 |1787 2895
我能够在单独的文件中获取 --net/eth0- 的值。但我想使用 3924B 值并删除最后一个字符 B/K/M。如果它的 K 则将剩余的数字乘以 1024,如果它的 M 使用 awk 则乘以 1024*1024。
例如,如果它是 37K:我想要 37888 (37*1024)。
到目前为止,我可以使用以下代码获取另一个文件中的值:
dstat $Intrfc $Intrvl $repNo | sed '1,2d' | awk -F '|' '{print }' | awk '{print "," }' | sed "s/^/`date +%m:%d:%Y:%H:%M:%S`,/" >> $outFile
您只需在 awk
中添加 0
即可删除 B
等
dstat $Intrfc $Intrvl $repNo awk -F\| 'NR>2 {split(,a," ");print a[1]+0","a[2]+0}'
0,0
3924,7549
3766,2648
有数学:
awk -F\| 'NR>2 {split(,a," ");a[1]*=(a[1]~/K$/?1024:1);a[1]*=(a[1]~/M$/?1048576:1);a[2]*=(a[2]~/K$/?1024:1);a[2]*=(a[2]~/M$/?1048576:1);print a[1]","a[2]}'
这是一种方法。根据要求,它将 K
数字乘以 1024,M
数字乘以 1048576。它需要 GNU awk
:
dstat $Intrfc $Intrvl $repNo | awk -F '[| ]+' -v d=$(date +%m:%d:%Y:%H:%M:%S) -v OFS=, 'function cvt(x){return lshift(x, 10*(x~/K/)+20*(x~/M/))} NR>2 {print d,cvt(),cvt()}'
说明
-F '[| \t]+'
这会将字段分隔符设置为空格 and/or 竖线的任意组合。使用此字段分隔符,net/eth0 recv
是字段 10,writ
是字段 11。
-v d=$(date +%m:%d:%Y:%H:%M:%S)
这会创建一个 awk
变量 d
并将其分配给 date
命令的输出。
-v OFS=,
这会将输出字段分隔符设置为逗号。
function cvt(x){return lshift(x, 10*(x~/K/)+20*(x~/M/))}
这将创建一个转换函数,如果数字以 K
结尾则乘以 1024,如果数字以 M
结尾则乘以 1048576。
乘法是通过将数字分别左移 10 位或 20 位来实现 K 或 M。
请注意,此函数利用了 awk 的松散类型。
NR>2 {print d,cvt(),cvt()}
这将打印输出。 NR
是行号。跳过前两行,对于所有后面的行(NR>2
),打印日期,然后是转换后的第 10 列和转换后的第 11 列。
首先不要在管道蛇中使用多个awk
s 和sed
s。可以一步一步完成awk
。这是一个可能的解决方案:
awk -F"[ \t|]+" -v dt=$(date +%m:%d:%Y:%H:%M:%S) '
function num(n) {
if (n ~ "B$") n=substr(n,1,length(n)-1);
else if (n ~ "K$") n=substr(n,1,length(n)-1)*1024;
else if (n ~ "M$") n=substr(n,1,length(n)-1)*1024*1024;
return n;
}
NR>2{print num()","num()","dt}
' <<TXT
----total-cpu-usage---- -dsk/total- --net/eth0- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
3 2 95 1 0 0|4035B 143k| 0 0 | 0 0 |1539 2511
3 3 94 0 0 0| 0 24k|3924K 7549B| 0 0 |1821 2851
3 3 94 0 0 0| 0 84k|3766M 2648B| 0 0 |1787 2895
TXT
输出:
0,0,01:07:2015:09:32:24
4018176,7549,01:07:2015:09:32:24
3.94894e+09,2648,01:07:2015:09:32:24
一个更短的版本,更大的数字输出更好(我借用了 John1024 的乘法思想):
awk -F"[ \t|]+" -v dt=$(date +%m:%d:%Y:%H:%M:%S) '
function num(n) {
m="";
if (n~"[^0-9]$") {m=substr(n,length(n),1);n=substr(n,1,length(n)-1);}
return n * 2**(m=="K"?10:m=="M"?20:0);
}
NR>2{printf("%d,%d,%s\n", num(),num(),dt)}
'
输出:
0,0,01:07:2015:09:30:27
4018176,7549,01:07:2015:09:30:27
3948937216,2648,01:07:2015:09:30:27
在示例中我使用了 here-doc 而不是管道 dstat
因为我没有安装 dstat。
希望对您有所帮助。
我正在使用 dstat 工具获取 eth0 接口的网络使用情况。 dstat 给出如下输出:
----total-cpu-usage---- -dsk/total- --net/eth0- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
3 2 95 1 0 0|4035B 143k| 0 0 | 0 0 |1539 2511
3 3 94 0 0 0| 0 24k|3924B 7549B| 0 0 |1821 2851
3 3 94 0 0 0| 0 84k|3766B 2648B| 0 0 |1787 2895
我能够在单独的文件中获取 --net/eth0- 的值。但我想使用 3924B 值并删除最后一个字符 B/K/M。如果它的 K 则将剩余的数字乘以 1024,如果它的 M 使用 awk 则乘以 1024*1024。 例如,如果它是 37K:我想要 37888 (37*1024)。
到目前为止,我可以使用以下代码获取另一个文件中的值:
dstat $Intrfc $Intrvl $repNo | sed '1,2d' | awk -F '|' '{print }' | awk '{print "," }' | sed "s/^/`date +%m:%d:%Y:%H:%M:%S`,/" >> $outFile
您只需在 awk
中添加 0
即可删除 B
等
dstat $Intrfc $Intrvl $repNo awk -F\| 'NR>2 {split(,a," ");print a[1]+0","a[2]+0}'
0,0
3924,7549
3766,2648
有数学:
awk -F\| 'NR>2 {split(,a," ");a[1]*=(a[1]~/K$/?1024:1);a[1]*=(a[1]~/M$/?1048576:1);a[2]*=(a[2]~/K$/?1024:1);a[2]*=(a[2]~/M$/?1048576:1);print a[1]","a[2]}'
这是一种方法。根据要求,它将 K
数字乘以 1024,M
数字乘以 1048576。它需要 GNU awk
:
dstat $Intrfc $Intrvl $repNo | awk -F '[| ]+' -v d=$(date +%m:%d:%Y:%H:%M:%S) -v OFS=, 'function cvt(x){return lshift(x, 10*(x~/K/)+20*(x~/M/))} NR>2 {print d,cvt(),cvt()}'
说明
-F '[| \t]+'
这会将字段分隔符设置为空格 and/or 竖线的任意组合。使用此字段分隔符,net/eth0 recv
是字段 10,writ
是字段 11。
-v d=$(date +%m:%d:%Y:%H:%M:%S)
这会创建一个
awk
变量d
并将其分配给date
命令的输出。-v OFS=,
这会将输出字段分隔符设置为逗号。
function cvt(x){return lshift(x, 10*(x~/K/)+20*(x~/M/))}
这将创建一个转换函数,如果数字以
K
结尾则乘以 1024,如果数字以M
结尾则乘以 1048576。乘法是通过将数字分别左移 10 位或 20 位来实现 K 或 M。
请注意,此函数利用了 awk 的松散类型。
NR>2 {print d,cvt(),cvt()}
这将打印输出。
NR
是行号。跳过前两行,对于所有后面的行(NR>2
),打印日期,然后是转换后的第 10 列和转换后的第 11 列。
首先不要在管道蛇中使用多个awk
s 和sed
s。可以一步一步完成awk
。这是一个可能的解决方案:
awk -F"[ \t|]+" -v dt=$(date +%m:%d:%Y:%H:%M:%S) '
function num(n) {
if (n ~ "B$") n=substr(n,1,length(n)-1);
else if (n ~ "K$") n=substr(n,1,length(n)-1)*1024;
else if (n ~ "M$") n=substr(n,1,length(n)-1)*1024*1024;
return n;
}
NR>2{print num()","num()","dt}
' <<TXT
----total-cpu-usage---- -dsk/total- --net/eth0- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
3 2 95 1 0 0|4035B 143k| 0 0 | 0 0 |1539 2511
3 3 94 0 0 0| 0 24k|3924K 7549B| 0 0 |1821 2851
3 3 94 0 0 0| 0 84k|3766M 2648B| 0 0 |1787 2895
TXT
输出:
0,0,01:07:2015:09:32:24
4018176,7549,01:07:2015:09:32:24
3.94894e+09,2648,01:07:2015:09:32:24
一个更短的版本,更大的数字输出更好(我借用了 John1024 的乘法思想):
awk -F"[ \t|]+" -v dt=$(date +%m:%d:%Y:%H:%M:%S) '
function num(n) {
m="";
if (n~"[^0-9]$") {m=substr(n,length(n),1);n=substr(n,1,length(n)-1);}
return n * 2**(m=="K"?10:m=="M"?20:0);
}
NR>2{printf("%d,%d,%s\n", num(),num(),dt)}
'
输出:
0,0,01:07:2015:09:30:27
4018176,7549,01:07:2015:09:30:27
3948937216,2648,01:07:2015:09:30:27
在示例中我使用了 here-doc 而不是管道 dstat
因为我没有安装 dstat。
希望对您有所帮助。