116

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

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

XCODE=`expr $XCODE + 1`

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

4

7 回答 7

140

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

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

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

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

于 2008-09-23T22:29:16.607 回答
120

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

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

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

也许

while ... do ... done < <(echo "$OUTPUT")
于 2008-09-23T22:37:40.080 回答
10

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

#!/bin/bash
cat /tmp/randomFile | (while read line
do
    LINE="$LINE $line"
done && echo $LINE )
于 2014-11-27T16:24:09.820 回答
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

于 2014-11-02T16:49:48.510 回答
2
 #!/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

看看这些变化是否有帮助

于 2008-09-23T22:03:29.100 回答
2

另一种选择是将结果从子 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)
于 2011-04-11T17:33:36.783 回答
1

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

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

于 2016-08-24T13:04:02.057 回答