以awk的特定顺序打印文件

时间:2019-02-15 04:54:18

标签: shell awk sed

我正在跟踪此链接https://stackoverflow.com/a/54599800/10220825

file.txt

Iteration 1
RAM: +2s
Cache: +142ms (total +417ms)

Iteration 2
RAM: +184ms
Cache: +172ms
Searchms: +131ms (total +385ms)

Iteration 3
RAM: +149ms
Searchms: +3.2s

我想从时间值中删除ms or s,而不是从名称中删除(例如,它不应删除Searchms to Search)。另外,如果时间值包含s into ms,我想将multiply into 1000转换为s,并相应地打印结果。

预期输出:

RAM: 2000 184 149
Cache: 142 172
Searchms: 131 3200

try.awk

/:/{vals[$1]=vals[$1] OFS $2+0}
END {
         for (key in vals)
          print key vals[key]
}

执行时:awk -f try.awk file.txt

代码输出:

Cache: 142 172
Searchms: 131 3.2
RAM: 2 184 149

在我的输出s is not converting to ms.中,建议我如何修改上面的源代码try.awk来将s转换为ms。


新测试用例: file.txt

Iteration 1
RAM: +2s342ms

Iteration 2
RAM: +2s

Iteration 3
RAM: +149ms

代码:

/:/ && $2 ~/ms$/{vals[$1]=vals[$1] OFS $2+0;next}
/:/ && $2 ~/[^m]s$/{vals[$1]=vals[$1] OFS ($2+0)*1000}
END {
         for (key in vals)
          print key vals[key]
}

预期输出:

RAM: 2342 2000 149

输出:

RAM: 2 2000 149

2 个答案:

答案 0 :(得分:3)

您可以使用以下awk脚本:

/:/ && $2 ~/ms$/{vals[$1]=vals[$1] OFS $2+0;next}
/:/ && $2 ~/[^m]s$/{vals[$1]=vals[$1] OFS ($2+0)*1000}
END {
         for (key in vals)
          print key vals[key]
}

这将产生输出:

awk -f try.awk file.txt 
Cache: 142 172
Searchms: 131 3200
RAM: 2000 184 149

说明:

  • 条件$2 ~/ms$/将检查我们是否与ms有一行,在这种情况下,逻辑与以前相同,并且next将迫使awk跳至下一行。
  • /:/ && $2 ~/[^m]s$/{vals[$1]=vals[$1] OFS ($2+0)*1000},当我们达到此范围时,我们知道一行在s中具有单位,并将其乘以1000即可将其转换为ms

为了满足您的新要求,我将try.awk修改为:

/:/ && $2 ~/[0-9]+s[0-9]+ms$/{split($2,buff,/s/);vals[$1]=vals[$1] OFS (buff[1]+0)*1000+buff[2];next}
/:/ && $2 ~/ms$/{vals[$1]=vals[$1] OFS $2+0;next}
/:/ && $2 ~/[^m]s$/{vals[$1]=vals[$1] OFS ($2+0)*1000}
END {
         for (key in vals)
          print key vals[key]
}

输入:

$ cat file2.txt 
Iteration 1
RAM: +2s342ms

Iteration 2
RAM: +2s

Iteration 3
RAM: +149ms

输出:

$ awk -f try.awk file2.txt 
RAM: 2342 2000 149

答案 1 :(得分:2)

OP的小改编:

/:/{  vals[$1]=vals[$1] OFS $2*($2~/ms$/ ? 1 : 1000 ) }
END { for (key in vals) print key vals[key] }

备注:这不适用于所有版本的awk,这利用了gawk(和POSIX)的以下出色功能:

  

通过将字符串的任何数字前缀解释为数字,将字符串转换为数字:“ 2.5”转换为2.5,“ 1e3”转换为1,000,和“ 25fix”的数字值为25 。无法解释为有效数字的字符串将转换为零。

     

来源:Gnu Awk manual: Conversion of Strings and Numbers

此行为是Posix有效的,并且可以使用C函数atof来工作。但是,POSIX提供了第二种选择,可以将字符串转换为数字,其中“ 25fix”将转换为0。例如,在Oracle上就是这种情况:

Linux: GNU $ awk 'BEGIN{print "25fix"+0}'
25
SUN OS: SUNWesu $ /usr/bin/awk 'BEGIN{print "25fix"+0}'
0
SUN OS: SUNWxpg $ /usr/xpg4/bin/awk 'BEGIN{print "25fix"+0}'
25