Linux 在Bash脚本中使用带有转义字符的Awk
我正在为Linux系统编写一个shell脚本(使用Bash) 作为这个脚本的一部分,我使用awk获取ping请求丢弃的数据包的百分比。当从如下所示的终端执行时,该操作可以正常工作:Linux 在Bash脚本中使用带有转义字符的Awk,linux,bash,shell,awk,escaping,Linux,Bash,Shell,Awk,Escaping,我正在为Linux系统编写一个shell脚本(使用Bash) 作为这个脚本的一部分,我使用awk获取ping请求丢弃的数据包的百分比。当从如下所示的终端执行时,该操作可以正常工作: test=`ping gnu.org -c10 | tail -2`; echo $test | awk '{printf $6 "\b"}' 这将获取丢弃的数据包的百分比,并使用退格转义字符对其进行回显,以仅显示“0”,而不是“0%”-这是因为该值稍后用作整数值 在脚本中,代码如下所示: #Pings the g
test=`ping gnu.org -c10 | tail -2`; echo $test | awk '{printf $6 "\b"}'
这将获取丢弃的数据包的百分比,并使用退格转义字符对其进行回显,以仅显示“0”,而不是“0%”-这是因为该值稍后用作整数值
在脚本中,代码如下所示:
#Pings the gateway ten times and stores the result
local pingResults=`ping -c10 $gateway | tail -2`
#Uses awk to get the percentage of packets lost using \b to remove the %
local packetsLost=`echo $pingResults | awk '{printf $6 "\b"}'`
我从packetsLost返回值并回显它,它给出“0%”,完全忽略\b
有人能解释一下为什么在shell脚本中会发生这种情况,以及我如何补救这种情况吗
我知道还有其他选择,例如使用cut,但我希望线路尽可能简单高效。检查下一步:
echo 1x 2x 3x 4x 5x 6x 7x | awk '{printf $6 "\b"}' | od -cb
您将获得下一个输出:
0000000 6 x \b
066 170 010
所以,当你运行
echo 1x 2x 3x 4x 5x 6x 7x | awk '{printf $6 "\b"}'
你被打印出来了:
- 字符6
- 字符x
- 字符退格(是什么导致在终端中删除字符)
aaa=$(echo 1x 2x 3x 4x 5x 6x 7x | awk '{printf $6 "\b"}')
将结果存储到aaa
,并显示其内容:
echo $aaa | od -bc
0000000 066 170 010 012
6 x \b \n
如果需要相同的结果,请使用:
echo -n $aaa
总之,使用:
local packetsLost=`echo $pingResults | awk '{printf $6 "\b"}'`
echo -n $packetLost
awk'{sub(/%/,“”,$6);printf$6}
或
awk'{print substr($6,1,length($6)-1)}
OMG!基于单词计数解析人类可读字符串是完全不可维护的(“只写”)和不可预测的。尽量避免。其实很简单:
$ ping -q gnu.org -c10 |\
gawk '{ if (match ($0, /([[:digit:]]+(\.[[:digit:]]+)?)% packet loss/, a)) print a[1]; }'
0
a[1]
此处对应于regexp中的第一个()
组
另外,当您解析人类可读的输出时,有必要确保语言环境(即语言)与您在编写脚本时预期的相同,因此在实际代码中,ping调用应该如下所示:
local pingResults=$(LANG=C ping -q -c10 "$gateway")
(即使看起来,
iputils ping
特别没有任何翻译。)终端的外壳和脚本的外壳一样吗?是的,bash不仅用于gsub
在awk中去掉%
字符,而不是玩打印转义技巧?试试printf(%s),substr($6,1,length($6)-1))
。我觉得Awk是实现我所需要的最干净、最简单的方法。在我使用函数时,echo起着返回的作用。其思想是收集各种数据,最后将其放入一个大的格式化字符串中进行输出。我已经尝试了您的建议,但它仍然提供0%、100%等。在这种情况下,您需要从输出中删除%
。(您可以在转储中看到,\b
不会删除它。)谢谢!这是一个很好的答案。我没有在程序上使用ping,所以我忽略了quiet选项。它只匹配小数点后的数字。e、 g.99.9%的数据包丢失
将与9
相匹配。如果您关心区域设置,则应使用[[:digit:]
而不是[0-9]
。另外,不要将条件放在操作部分中,只需将其放在条件部分:gawk'match($0,/([0-9]+)%packet loss/,a){print a[1]}
@JohnB您在哪里读到的ping
将百分比舍入到十分之一,而不是整数。我做了一些测试,得到了如下结果:145个数据包传输,127个接收,12%的数据包丢失,时间144676ms
while(145− 127) / 145 ≈ 12.4%。@DimitryAlexandrov在OSX上试试这个,你会看到的。