Bash 变量范围

请解释一下为什么最后一个 echo语句是空白的?我期望 XCODE在 while 循环中增加到值1:

#!/bin/bash
OUTPUT="name1 ip ip status" # normally output of another command with multi line output


if [ -z "$OUTPUT" ]
then
echo "Status WARN: No messages from SMcli"
exit $STATE_WARNING
else
echo "$OUTPUT"|while read NAME IP1 IP2 STATUS
do
if [ "$STATUS" != "Optimal" ]
then
echo "CRIT: $NAME - $STATUS"
echo $((++XCODE))
else
echo "OK: $NAME - $STATUS"
fi
done
fi


echo $XCODE

I've tried using the following statement instead of the ++XCODE method

XCODE=`expr $XCODE + 1`

它也不会在 while 语句之外打印。我想我遗漏了一些关于变量作用域的东西,但是 ol’man 页面没有显示给我看。

110313 次浏览
 #!/bin/bash
OUTPUT="name1 ip ip status"
+export XCODE=0;
if [ -z "$OUTPUT" ]
----


echo "CRIT: $NAME - $STATUS"
-                    echo $((++XCODE))
+                    export XCODE=$(( $XCODE + 1 ))
else


echo $XCODE

see if those changes help

因为您是通过管道进入 while 循环,所以创建了一个子 shell 来运行 while 循环。

现在,这个子进程有自己的环境副本,不能传递任何副本 变量返回到其父进程(与任何 unix 进程一样)。

因此,您需要重新构造,这样您就不会插入到循环中。 或者,您可以运行一个函数,例如,和 echo的值您 希望从子进程返回。

Http://tldp.org/ldp/abs/html/subshells.html#subshell

问题是,与管道放在一起的进程是在子 shell 中执行的(因此具有自己的环境)。无论在 while中发生什么,都不会影响管道之外的任何东西。

可以通过将管道重写为

while ... do ... done <<< "$OUTPUT"

也许吧

while ... do ... done < <(echo "$OUTPUT")

另一种选择是将结果从子 shell 输出到一个文件中,然后在父 shell 中读取它。比如

#!/bin/bash
EXPORTFILE=/tmp/exportfile${RANDOM}
cat /tmp/randomFile | while read line
do
LINE="$LINE $line"
echo $LINE > $EXPORTFILE
done
LINE=$(cat $EXPORTFILE)

还有一个选择:

#!/bin/bash
cat /some/file | while read line
do
var="abc"
echo $var | xsel -i -p  # redirect stdin to the X primary selection
done
var=$(xsel -o -p)  # redirect back to stdout
echo $var

编辑: Here, xsel is a requirement (install it). 或者,您可以使用 xlip: xclip -i -selection clipboard 而不是 xsel -i -p

这应该也可以工作(因为 echo 和 while 在同一个子 shell 中) :

#!/bin/bash
cat /tmp/randomFile | (while read line
do
LINE="$LINE $line"
done && echo $LINE )

I got around this when I was making my own little du:

ls -l | sed '/total/d ; s/  */\t/g' | cut -f 5 |
( SUM=0; while read SIZE; do SUM=$(($SUM+$SIZE)); done; echo "$(($SUM/1024/1024/1024))GB" )

关键在于,我用包含 SUM 变量和 while 的()创建了一个子 shell,但是我通过管道进入了整个()而不是 while 本身,这样就避免了陷入陷阱。