Bash变量范围

时间:2008-09-23 21:56:11

标签: bash

请向我解释为什么最后一个“回声”声明是空白的?我希望它在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

我尝试使用以下语句代替++ XCODE方法

XCODE=`expr $XCODE + 1`

它也不会在while语句之外打印。我想我在这里遗漏了一些关于变量范围的东西,但是ol'手册页并没有显示给我。

7 个答案:

答案 0 :(得分:102)

因为你正在进入while循环,所以创建了一个子shell来运行while循环。 现在这个子进程拥有自己的环境副本,无法通过任何环境 变量返回其父级(如在任何unix进程中)。

因此,您需要进行重组,以便不会进入循环。 或者,您可以在函数中运行,例如并回显您的值 希望从子流程返回。

http://tldp.org/LDP/abs/html/subshells.html#SUBSHELL

答案 1 :(得分:99)

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

您可以通过将管道重写为

来解决您的具体示例
while ... do ... done <<< "$OUTPUT"

或者

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

答案 2 :(得分:8)

这也应该有效(因为echo和while在同一个子shell中):

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

答案 3 :(得分:3)

还有一个选择:

#!/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

编辑: 在这里,xsel是一个要求(安装它)。 或者,您可以使用xclip:     xclip -i -selection clipboard 代替     xsel -i -p

答案 4 :(得分:1)

 #!/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

查看这些更改是否有帮助

答案 5 :(得分:0)

另一种选择是将结果输出到子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)

答案 6 :(得分:0)

当我制作自己的小杜时,我解决了这个问题:

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本身,这避免了陷阱。