在shell中,经常会处理一些命令的输出内容,如果输出内容中有多个字符串需要截取出来赋值给多个变量,比较简单的方法是先将输出内容记录到一个临时文件,然后重复多次awk指令,将输出内容分别截取到不同变量中。
但是上述方法虽然逻辑简单,但是处理效率较低,重复执行的awk命令完全没有"营养"。
举例,需要将uptime
指令输出的3个load值记录下来(1分钟,5分钟和15分钟),简餐的uptime
输出类似如下
09:12:11 up 494 days, 19:09, 1 user, load average: 1.70, 1.60, 1.73
注意,上述输出内容中混合了多种分隔符号,例如
空格
,:
,,
,其中如果用空格来作为分隔符还需要注意多个空格。为了简化和明确分隔符,所以首先过滤掉空格
,否则字符串中多少不一的空格符会让我们的awk
无所适从。这里我们使用非常常规的tr
命令
uptime | tr -d " "
此时输出结果
09:12:11up494days,19:09,1user,loadaverage:1.70,1.60,1.73
接下来就很容易结合使用:
和,
分隔符来过滤出3个负载值:
uptime | tr -d " " | awk -F "[:,]" '{print $8" "$9" "$10}'
输出内容就是
1.70 1.60 1.73
但是,问题来了,难道我还要一次次重复过滤赋值给变量么?
NO
shell支持
read a b c <<<$(echo 1 2 3) ; echo "$a|$b|$c"
这里采用了 $(echo X Y Z)
,分别用空格符分隔的3个值echo
出来后只要加上$()
就可以转换成变量,就可以通过<<<
读取到变量中。
所以,我们的脚本命令修改成
read load1 load5 load15 <<< $(echo $(uptime | tr -d " " | awk -F "[:,]" '{print $8" "$9" "$10}'))
注意:这里使用的第一次
$()
是为了将命令输出转换成变量,然后让echo
指令打印出这个变量。然后再套上一个$()
将echo
输出的结果再次转换成变量。
此时可以非常容易就检查
$echo $load1
1.70
$echo $load5
1.60
$echo $load15
1.73