Bash 变量作用域

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/124167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:41:43  来源:igfitidea点击:

Bash variable scope

bashscopepipe

提问by Matt P

Please explain to me why the very last echostatement is blank? I expect that XCODEis incremented in the while loop to a value of 1:

请向我解释为什么最后一个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 ++XCODEmethod

我尝试使用以下语句而不是++XCODE方法

XCODE=`expr $XCODE + 1`

and it too won't print outside of the while statement. I think I'm missing something about variable scope here, but the ol' man page isn't showing it to me.

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

回答by pixelbeat

Because you're piping into the while loop, a sub-shell is created to run the while loop.

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

Now this child process has its own copy of the environment and can't pass any variables back to its parent (as in any unix process).

现在这个子进程有它自己的环境副本并且不能将任何变量传递回它的父进程(就像在任何 unix 进程中一样)。

Therefore you'll need to restructure so that you're not piping into the loop. Alternatively you could run in a function, for example, and echothe value you want returned from the sub-process.

因此,您需要重组,以免进入循环。或者,您可以在一个函数中运行,例如,echo您希望从子流程返回的值。

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

http://tldp.org/LDP/abs/html/subshel​​ls.html#SUBSHELL

回答by mweerden

The problem is that processes put together with a pipe are executed in subshells (and therefore have their own environment). Whatever happens within the whiledoes not affect anything outside of the pipe.

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

Your specific example can be solved by rewriting the pipe to

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

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

or perhaps

也许

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

回答by sano

This should work as well (because echo and while are in same subshell):

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

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

回答by Rammix

One more option:

还有一种选择:

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

EDIT: Here, xsel is a requirement (install it). Alternatively, you can use xclip: xclip -i -selection clipboardinstead of xsel -i -p

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

回答by Kent Fredric

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

看看这些变化是否有帮助

回答by freethinker

Another option is to output the results into a file from the subshell and then read it in the parent shell. something like

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

回答by Adrian May

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" )

The point is that I make a subshell with ( ) containing my SUM variable and the while, but I pipe into the whole ( ) instead of into the while itself, which avoids the gotcha.

关键是我用 ( ) 制作了一个包含我的 SUM 变量和 while 的子外壳,但我通过管道进入整个 () 而不是进入 while 本身,这避免了陷阱。