2008-09-23 13 views
87

Bitte erklären Sie mir, warum die allerletzte "echo" Anweisung leer ist? Ich gehe davon aus, dass es in der while-Schleife auf einen Wert von 1 erhöht wurde:Bash variabler Bereich

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

Ich habe versucht, die folgende Anweisung anstelle der ++ XCODE Methode

XCODE=`expr $XCODE + 1` 

und es zu pflegen drucken außerhalb der while-Anweisung. Ich denke, ich verpasse hier etwas über den variablen Bereich, aber die alte man-Seite zeigt es mir nicht.

+0

Wo initialisierst du XCODE zu etwas, das inkrementiert werden kann? –

+0

Ich habe versucht, ein "XCODE = 0" an der Spitze des Codes, außerhalb der while-Anweisung –

+0

zu werfen. Ohne die cruft, funktioniert es für mich. #!/Bin/bash für i in 1 2 3 4 5; tun echo $ ((++ XCODE)) getan echo "fin:" $ XCODE Ich denke, Ihr Problem hat nichts mit variabler Scoping und alles zu tun, was während der Weile passiert. –

Antwort

91

helfen, weil Sie in der while-Schleife sind Rohrleitungen, eine Unterschale erstellt die while-Schleife laufen. Nun hat dieser untergeordnete Prozess eine eigene Kopie der Umgebung und kann keine Variablen an den übergeordneten Prozess übergeben (wie bei jedem Unix-Prozess).

Daher müssen Sie neu strukturieren, so dass Sie nicht in die Schleife hineinpassen. Alternativ können Sie auch eine Funktion ausführen und den Wert , der vom Unterprozess zurückgegeben werden soll, zurückgeben.

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

+0

Macht Sinn .. Danke. Sieht so aus, als ob die Funktion der richtige Weg für mich ist. –

+1

das beantwortete so viele der scheinbar zufälligen Probleme, die ich mit bash scripting lief. –

+0

Diese perfekte Antwort stört mich sehr und erklärt ein wirklich seltsames Verhalten in unserem CI-System. – KayCee

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 

sehen, ob diese Änderungen

+0

Wenn ich das mache, bekomme ich jetzt eine "0" für die letzte Echo-Anweisung. Ich erwarte jedoch, dass der Wert 1 nicht Null ist. Warum auch die Verwendung von Export? Ich nehme an, dass das in die Umwelt drängt? –

93

Das Problem ist, dass mit einem Rohr zusammen Prozesse in Subshells ausgeführt werden (und damit ihre eigene Umwelt hat). Was auch immer innerhalb der while passiert, beeinflusst nichts außerhalb der Rohrleitung.

Ihr spezifisches Beispiel kann durch Umschreiben des Rohres zu

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

oder vielleicht

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

Brilliant. Ich hatte die < Jonathan

+3

Ich kannte auch die '<(command)' Syntax nicht, und das hat mir eine Menge Zeit und Kopfschmerzen erspart. ein großes +1 an Sie Herr :) –

+26

Für diejenigen, die auf diese verwirrt über was die ganze <() -Syntax ist (wie ich war), es heißt "Process Substitution", und die oben angegebene spezifische Verwendung kann sein hier zu sehen: http://mywiki.wooledge.org/ProcessSubstitution –

0

Eine weitere Option zur Ausgabe ist von der Subshell die Ergebnisse in eine Datei gelöst werden und lesen Sie es dann in die Mutterschale. so etwas wie

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

Eine weitere 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: Hier xsel ist eine Anforderung (installieren). Alternativ können Sie verwenden xclip: xclip -i -selection clipboard statt xsel -i -p

+0

Ich erhalte einen Fehler: ./scraper.sh: Zeile 111: xsel: Befehl nicht gefunden ./scraper.sh: Zeile 114: xsel: Befehl nicht gefunden – 3kstc

+0

@ 3kstc offensichtlich installieren xsel. Sie können auch xclip verwenden, aber seine Verwendung ist ein wenig anders. Hauptpunkt hier: 1. Sie setzen die Ausgabe in eine Zwischenablage (3 von ihnen in Linux), 2. - Sie greifen es von dort und senden an stdout. – Rammix

4

Dies sollte auch funktionieren (weil Echo und während in derselben Subshell sind):

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

ich um dieses bekam, als ich machen mein eigen klein ich:

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

Der Punkt ist, dass ich ein Sub-Shell mit(), die meiner SUM Variable und die während machen, aber ich pipe in das ganze() statt in die while selbst, die die gotcha vermeidet.

Verwandte Themen