web-dev-qa-db-ja.com

Bash変数スコープ

最後の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ステートメントの外側には出力されません。私はここで変数スコープについて何かを見逃していると思いますが、古いマニュアルページは私にそれを示していません。

102
Matt P

Whileループにパイプしているため、whileループを実行するためのサブシェルが作成されます。

現在、この子プロセスには環境の独自のコピーがあり、変数を親に戻すことはできません(unixプロセスの場合と同様)。

したがって、ループにパイプしないように再構築する必要があります。あるいは、たとえば、関数で実行し、サブプロセスから返される値をechoにすることもできます。

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

109
pixelbeat

問題は、パイプでまとめられたプロセスがサブシェルで実行されることです(したがって、独自の環境があります)。 while内で何が起こっても、パイプ以外の部分には影響しません。

あなたの特定の例は、パイプを

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

多分

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

これは同様に機能するはずです(echoとwhileは同じサブシェルにあるため):

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

もう1つのオプション:

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

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

これらの変更が役立つかどうかを確認します

1
Kent Fredric

別のオプションは、結果をサブシェルからファイルに出力し、親シェルでそれを読み取ることです。何かのようなもの

#!/bin/bash
EXPORTFILE=/tmp/exportfile${RANDOM}
cat /tmp/randomFile | while read line
do
    LINE="$LINE $line"
    echo $LINE > $EXPORTFILE
done
LINE=$(cat $EXPORTFILE)
0
freethinker

私は自分の小さなデュを作っているときにこれを回避しました:

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を含む()でサブシェルを作成することですが、while自体ではなく全体()にパイプすることで、問題を回避します。

0
Adrian May