Bash变量范围

Bash变量范围,bash,scope,pipe,Bash,Scope,Pipe,请向我解释为什么最后一个echo语句是空的?我希望while循环中XCODE的值会增加到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_WARNIN

请向我解释为什么最后一个
echo
语句是空的?我希望while循环中
XCODE
的值会增加到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'手册页没有向我展示它

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

查看这些更改是否有帮助

,因为您要通过管道进入while循环,因此会创建一个子shell来运行while循环

现在,这个子进程有自己的环境副本,无法传递任何 变量返回到其父级(就像在任何unix进程中一样)

因此,您需要重新构造,以避免管道进入循环。 或者,您可以在函数中运行,例如,
echo
希望从子进程返回


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

您的具体示例可以通过将管道重写为

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

当。。。做done另一个选项是将结果从子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
编辑: 在这里,xsel是一个需求(安装它)。 或者,您可以使用xclip:
xclip-i-选择剪贴板
而不是
xsel-i-p

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


我是在做自己的小杜邦的时候想到这个的:

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本身,这样可以避免出现问题。

执行此操作时,我现在为最后一个echo语句打印一个“0”。但是,我希望值为1而不是零。还有,为什么使用出口?我认为这会迫使它进入环境?对于那些正在困惑于整个过程的人来说,替代是每个人都应该经常使用的东西!它非常有用。我做了一些类似于
vimdiff的事情,我遇到了这个问题,重构管道以保存第一阶段的输出并像这样编写非常简单。非常感谢您为我节省了数小时的研究和实验时间。您在哪里将XCODE初始化为可以递增的内容?我已尝试在代码顶部抛出一个“XCODE=0”,在while语句之外,如果没有cruft,它对我很有效。#/bin/bash代表我在12345;do echo$(++XCODE))done echo“fin:$XCODE我认为您的问题与变量作用域无关,而与期间发生的事情有关。同意。。这似乎和“边读边读”有关loop?关于这一点,有一个Bash常见问题解答:这只是回答了我在使用Bash脚本时遇到的许多看似随机的问题。这个完美的答案让我非常不安,并解释了我们CI系统中一个非常奇怪的行为。我得到一个错误:./scraper.sh:line 111:xsel:command not found./scraper.sh:line 114:xsel:command notfound@3kstc 显然,要安装xsel。另外,您可以使用xclip,但它的用法有点不同。这里的要点是:第一,将输出放入剪贴板(linux中有3个),第二,从那里抓取并发送到stdout。
#!/bin/bash
cat /tmp/randomFile | (while read line
do
    LINE="$LINE $line"
done && echo $LINE )
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" )