Bash変数スコープ


87

最後の "echo"文が空白である理由を説明してください。私は次の文の代わり++ XCODE方法

XCODE=`expr $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 

:私は、それが1の値にwhileループで増加していることを期待しますwhileステートメントの外側。私はここで変数のスコープについて何か不足していると思うが、olのマニュアルページはそれを私に示していない。

  0

ここで、XCODEをインクリメントできるものに初期化しますか? 23 9月. 082008-09-23 21:57:56

  0

while文の外側で、コードの先頭に "XCODE = 0"をスローしようとしました 23 9月. 082008-09-23 21:59:21

  0

裂け目なしで、それは私のために働きます。 #!/ bin/bash for i in 1 2 3 4 5; do echo $((++ XCODE)) done echo "fin:" $ XCODE 私は、あなたの問題は変数スコープと何が起こっているのかとは関係ないと思います。 23 9月. 082008-09-23 22:08:23

  0

合意しました。 "while read"ループと関係があるようですね。 23 9月. 082008-09-23 22:11:27

91

を助けるかどうかを確認します。 この子プロセスはそれ自身の環境コピーを持ち、 変数をその親に戻すことはできません(UNIXプロセスの場合のように)。

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

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

  0

感謝します..ありがとう。機能が私のために行く方法であるように見えます。 23 9月. 082008-09-23 22:36:03

+1

これはちょうど私がbashスクリプトを使って実行していた一見無作為の問題の多くに答えました。 27 1月. 152015-01-27 14:29:10

  0

この完璧な答えは私を大いに怒らせ、私たちのCIシステムの本当に奇妙な行動を説明します。 06 4月. 172017-04-06 08:29:48


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 

それらの変更は、あなたがwhileループの中にパイプしているので、サブシェルが、whileループを実行するために作成され

  0

これを実行すると、最後のecho文を出力するための "0"が得られるようになりました。しかし私は値が1ではないことを期待しています。また、なぜ輸出の使用?私はそれを環境に強制すると思いますか? 23 9月. 082008-09-23 22:09:59


93

問題は、パイプと一緒に入れプロセスはサブシェルで実行されていることである(したがって、自分の環境を持っています)。 while内で何が起こっても、パイプの外側には何も影響しません。

特定の例では、別のオプションは、出力にサブシェルからファイルへの結果であり、その後にそれを読ん

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

または多分

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

ブリリアント。前に<構文を見たことがなかったので、それを読む必要がありますが、これは扱いになります。入力コマンドを最初ではなく最後に置くのは奇妙ですが、それは機能します。 31 10月. 082008-10-31 19:32:03

+3

私は '<(command)'構文も知らなかったので、これは私に多くの時間と頭痛をもたらしました。あなたに大きな+1: 30 1月. 132013-01-30 12:29:39

+26

これは(私のような)全体の<()構文が混乱しているのを見ている人にとっては、これは「プロセス置換」と呼ばれ、上記の具体的な使用方法はhttp://mywiki.wooledge.org/ProcessSubstitution 19 2月. 132013-02-19 14:53:46

  0

*ありがとうございました*これは私が探していたものです! 04 4月. 142014-04-04 03:37:17


0

にパイプを書き換えることにより解決することができます親シェル。

#!/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使用することができます。代わりに xsel -i -p

  0

私はエラーが発生します:./scraper.sh:行111:xsel:コマンドが見つかりません ./scraper.sh:行114:xsel:コマンドが見つかりません 19 4月. 162016-04-19 01:57:49

  0

@ 3kstc明らかにxselをインストールします。また、xclipを使うこともできますが、その使い方は少し異なります。 ここでの主な点は、まず出力をクリップボード(3つはlinux)に入れ、2番目はクリップボードから取り出してstdoutに送ります。 09 5月. 162016-05-09 20:43:39


4

xclip -i -selection clipboard を(エコー、しばらくは同じサブシェルであるため)これは同様に動作するはずです:

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

0
私が作っていたとき、私はこの問題を回避まし

私自身の小さな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") 

ポイントは私のSUM変数とwhileを含むsubshel​​l()を作ることですが、しかし、私は全体の中に()の代わりに、それ自体の中にパイプを入れてしまい、それが邪魔になることはありません。