在 bash -c 中设置变量

Setting variable in bash -c

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

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

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

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

/usr/bin/bash 你开始一个子shell。 shell 完成后,shell 中的所有设置都将丢失。
以下 sub 在 subshell 中设置并在回显之前丢失:

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

是否要在子程序中设置变量shell,使用 stdout 传输值:

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

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

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

为了更直接的可见性:

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

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

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

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

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

从你的问题和例子来看,你手头的任务不需要你离开当前的环境,因此你不需要开始一个新的环境,也不需要担心数据丢失。

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

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