Область видимости переменной Bash - PullRequest
98 голосов
/ 24 сентября 2008

Пожалуйста, объясните мне, почему последнее утверждение "эхо" пустое? Я ожидаю, что он был увеличен в цикле 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. Я думаю, что я что-то упускаю из области видимости переменной, но старая страница руководства не показывает это мне.

Ответы [ 7 ]

102 голосов
/ 24 сентября 2008

Поскольку вы включаете цикл while, создается вспомогательная оболочка для запуска цикла while. Теперь этот дочерний процесс имеет свою собственную копию среды и не может передать Переменные возвращаются к его родителю (как в любом процессе unix).

Следовательно, вам нужно будет реструктурировать, чтобы не замыкаться в петле. В качестве альтернативы вы можете запустить функцию, например, и отобразить значение, которое вы хочу вернуть из подпроцесса.

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

99 голосов
/ 24 сентября 2008

Проблема состоит в том, что процессы, соединенные с конвейером, выполняются в подоболочках (и, следовательно, имеют собственную среду). Что бы ни происходило внутри while, это никак не повлияет на то, что находится за пределами трубы.

Ваш конкретный пример может быть решен путем переписывания канала в

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

или, возможно,

while ... do ... done < <(echo "$OUTPUT")
8 голосов
/ 27 ноября 2014

Это также должно работать (потому что echo и while находятся в одной и той же оболочке):

#!/bin/bash
cat /tmp/randomFile | (while read line
do
    LINE="$LINE $line"
done && echo $LINE )
3 голосов
/ 02 ноября 2014

Еще один вариант:

#!/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: Здесь xsel является требованием (установите его). В качестве альтернативы вы можете использовать xclip: xclip -i -selection clipboard вместо xsel -i -p

1 голос
/ 24 сентября 2008
 #!/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

посмотрите, помогут ли эти изменения

0 голосов
/ 24 августа 2016

Я справился с этим, когда делал свой собственный маленький 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, но я передаю всю трубку в целое (), а не в само время, что позволяет избежать ошибок.

0 голосов
/ 11 апреля 2011

Другой вариант - вывести результаты в файл из подоболочки и затем прочитать его в родительской оболочке. что-то вроде

#!/bin/bash
EXPORTFILE=/tmp/exportfile${RANDOM}
cat /tmp/randomFile | while read line
do
    LINE="$LINE $line"
    echo $LINE > $EXPORTFILE
done
LINE=$(cat $EXPORTFILE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...