14

我尝试设置从中获取接口 ip-address 的变量ifconfig并稍后读取。但是当我执行echo命令时,变量仍然是空的。请看我的代码:

/usr/bin/bash -c "HOST_IPS=$(/usr/bin/ifconfig | /usr/bin/awk 'BEGIN {cnt=0} {if($0 ~ /inet / && cnt==1) {print $2} cnt++}'); echo $HOST_IPS"

但是 /bin/echo 使用相同的命令可以正常工作:

/usr/bin/bash -c "echo $(/usr/bin/ifconfig | /usr/bin/awk 'BEGIN {cnt=0} {if($0 ~ /inet / && cnt==1) {print $2} cnt++}')"
4

3 回答 3

16

您必须$在最终的 echo 命令中转义符号,否则该变量$HOST_IPS将在子shell 生成之前被替换为命令字符串:

/usr/bin/bash -c "HOST_IPS=$(/usr/bin/ifconfig | /usr/bin/awk 'BEGIN {cnt=0} {if($0 ~ /inet / && cnt==1) {print $2} cnt++}'); echo \$HOST_IPS"

为了更直接的可见性:

#                                                  v-- insert backslash here
/usr/bin/bash -c "HOST_IPS=$(same as before); echo \$HOST_IPS"

与@gniourf_gniourf 的评论相反,实际上没有必要逃避其他美元符号。然而,正如所写,命令替换不是由子shell(!)执行的;它的结果被替换为传递给子shell的命令字符串。来电

mypid() { echo $$; }
bash -c "pid=$(mypid); echo \$pid; mypid"

演示它的工作方式:它会打印父 shell 的 PID,并且一旦抱怨mypid不是已知命令,因为子 shell 不知道该函数。

由于ifconfig | awk在父 shell 中运行命令不太可能出现问题,因此您可以保持命令替换部分不变。如果命令由子shell运行很重要,那么您也必须转义那里的所有内容。

于 2015-03-01T13:11:38.157 回答
0

从您的问题和示例来看,您手头的任务不需要您离开当前环境,因此您无需开始新环境并担心数据丢失。

HOST_IPS=();
while read -r;
  do [[ $REPLY =~ "inet "([^/]*) ]] && HOST_IPS+=(${BASH_REMATCH[1]});
done < <( ip -f inet address show )

如果您希望维护接口 IP 地址列表,您可以在当前 shell 中处理ip(or ) 的输出,而无需调用.ifconfigawk

于 2015-03-02T14:52:26.520 回答
0

/usr/bin/bash您一起启动一个子shell。当 shell 完成后,shell 中的所有设置都将丢失。
以下子设置在子shell中并在回显之前丢失:

/usr/bin/bash -c sub=1; echo $sub

你想在子shell中设置一个变量,使用标准输出来传输值:

sub=$(/usr/bin/bash -c "echo 1"); echo $sub
于 2015-03-01T13:07:32.637 回答