我正在尝试在我的Bash脚本代码中仅回显一个命令。
OVERRUN_ERRORS="$ifconfig | egrep -i "RX errors" | awk '{print $7}'"
echo ${OVERRUN_ERRORS}
然而,它给了我一个错误并且 $7 没有显示在命令中。我必须将它存储在一个变量中,因为我将在以后的某个时间处理输出(OVERRUN_ERRORS)。做到这一点的正确语法是什么?谢谢。
foo="bar | baz"
...将字符串“bar | baz”分配给名为foo
的变量;它不会作为管道运行bar | baz
。要做到这一点,您需要使用命令替换,可以使用现代的$()
语法或过时的反引号形式:
foo="$(bar | baz)"
由于问题中意图不明确,
正确的方法是使用函数来存储代码,而将输出存储在字符串中:
# store code in a function; this also works with pipelines
get_rx_errors() { cat /sys/class/net/"$1"/statistics/rx_errors; }
# store result of calling that function in a string
eth0_errors="$(get_rx_errors eth0)"
sleep 1 # wait a second for demonstration purposes, then...
# compare: echoing the stored value, vs calculating a new value
echo "One second ago, the number of rx errors was ${eth0_errors}"
etho "Right now, it is $(get_rx_errors eth0)"
eval
相关的安全风险,这通常被建议作为解决方法。
不要使用ifconfig
、grep
或者awk
来实现,只需要向内核请求你所需的数字即可:
#!/bin/bash
for device in /sys/class/net/*; do
[[ -e $device/statistics/rx_errors ]] || continue
rx_errors=$(<"${device}/statistics/rx_errors")
echo "Number of rx_errors for ${device##*/} is $rx_errors"
done
$(...)
捕获命令的输出,而不是双引号。overrun_errors=$(ifconfig | egrep -i "RX errors" | awk '{print $7}')
你在RX errors
周围的双引号是个问题。尝试使用;
OVERRUN_ERRORS="$ifconfig | egrep -i 'RX errors' | awk '{print $7}'"
为了查看命令的执行过程,您可以使用
set -v
或者
set -x
set -x
OVERRUN_ERRORS="$ifconfig | egrep -i 'RX errors' | awk '{print $7}'"
set +x
eval "$OVERRUN_ERRORS"
而不是 echo "$OVERRUN_ERRORS"
,我们可能会有一个不同的讨论(但这也将是关于在字符串中存储代码是一种不好的实践的讨论,其中有很多参考资料,如 BashFAQ#50 和 BashFAQ#48)。 - Charles Duffyecho
。他说“$7在命令中没有显示出来”,而不是“没有显示在输出中”。我认为我的解释完全合理。如果他说“我正在尝试运行一个命令”之类的话,我会谈论eval。 - CAB
$ifconfig
? - anubhavaOVERRUN_ERRORS
的赋值在当前写法下不执行任何命令(OVERRUN_ERRORS="$ifconfig | egrep -i "RX errors" | awk '{print $7}'"
)。你真正想做什么?bash -x the-script.sh
显示了什么? - Jonathan Lefflerifconfig
中提取这个信息的原因是什么,而不是直接从 sysfs 中提取(ifconfig 自己也是从那里得到的)? 直接从源头提取信息更可靠,这样就不用担心 ifconfig 输出格式的未来变化会破坏你的脚本了。 - Charles Duffygrep
和awk
没有必要。awk '/RX errors/ { print $7 }'
可以在一个命令中完成两者的工作。 - Charles Duffy