删除最后一个字符并使用 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 列。

首先不要在管道蛇中使用多个awks 和seds。可以一步一步完成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。

希望对您有所帮助。