2008-09-23 109 views
87

请向我解释为什么最后一个“回声”声明为空?我希望它在while循环递增到1的值:Bash可变范围

#!/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手册页并没有显示给我。

+0

你在哪里初始化XCODE到可以递增的东西? – 2008-09-23 21:57:56

+0

我试图在代码的顶部抛出一个“XCODE = 0”,在while语句之外 – 2008-09-23 21:59:21

+0

没有死锁,它适用于我。 #!/ bin/bash for i in 1 2 3 4 5;做 echo $((++ XCODE)) done echo“fin:”$ XCODE 我认为您的问题与变量范围界定无关,并且与此时发生的事情无关。 – 2008-09-23 22:08:23

回答

91

因为你进入管道while循环,创建一个子shell来运行while循环。 现在这个子进程拥有自己的环境副本,并且不能将任何 变量传递回其父级(如同在任何unix进程中一样)。

因此,您需要进行重组,以便不进入循环。 或者,你可以运行一个函数,例如回显你想要从子进程返回的值 。

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

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 

看看这些变化帮助

+0

当这样做时,我现在得到一个“0”来打印最后的回声。但是我希望这个值是1而不是零。另外,为什么使用导出?我认为这迫使它进入环境? – 2008-09-23 22:09:59

93

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

你的具体的例子可以通过重写管来解决,以

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

或许

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

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

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

这应该工作以及(因为回声,虽然在同一子shell):

#!/bin/bash 
cat /tmp/randomFile | (while read line 
do 
    LINE="$LINE $line" 
done && echo $LINE) 
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,但是我把它变成了整个()而不是它本身,这避免了这个问题。