Область изменения переменной хэш-памяти


87

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

  0

Где вы инициализируете XCODE тем, что может быть увеличено? 23 сен. 082008-09-23 21:57:56

  0

Я попытался выбросить «XCODE = 0» в верхней части кода, за пределами оператора while. 23 сен. 082008-09-23 21:59:21

  0

Без крутизны это работает для меня. #!/Bin/bash для i in 1 2 3 4 5; do echo $ ((++ XCODE)) сделано echo "fin:" $ XCODE Я думаю, что ваша проблема не имеет ничего общего с переменным охватом и все, что связано с тем, что происходит в то время. 23 сен. 082008-09-23 22:08:23

  0

Согласен. Кажется, что это связано с циклом «while read»? 23 сен. 082008-09-23 22:11:27

91

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

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

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

  0

Делает смысл .. Спасибо. Похоже, что функция - это путь для меня. 23 сен. 082008-09-23 22:36:03

+1

Это просто ответило на многие из кажущихся случайными проблем, с которыми я столкнулся с bash-скриптами. 27 янв. 152015-01-27 14:29:10

  0

Этот прекрасный ответ меня так сильно расстраивает и объясняет действительно странное поведение в нашей системе CI. 06 апр. 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 

посмотреть, если эти изменения помогают

  0

При этом я теперь получаю «0» для печати для последнего оператора эха. однако я ожидаю, что значение будет 1 не равно нулю. Кроме того, почему использование экспорта? Я предполагаю, что он заставляет его в окружающую среду? 23 сен. 082008-09-23 22:09:59


93

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

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

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

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

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

Блестящий. Я раньше не видел синтаксиса <<, поэтому должен прочитать его, но это работает. Кажется странным иметь команду ввода в конце, а не в начале, но она работает. 31 окт. 082008-10-31 19:32:03

+3

Я также не знал синтаксиса '<(command)', и это сэкономило мне много времени и головных болей. большой +1 к вам, сэр :) 30 янв. 132013-01-30 12:29:39

+26

Для тех, кто смотрит на это смущенно, что такое синтаксис <() (как и я), он называется «Замена процесса», а конкретное использование, описанное выше, может быть здесь: http://mywiki.wooledge.org/ProcessSubstitution 19 фев. 132013-02-19 14:53:46

  0

* спасибо * это было именно то, что я искал! 04 апр. 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 

EDIT: Здесь xsel требование (установить). Кроме того, вы можете использовать Xclip: xclip -i -selection clipboard вместо xsel -i -p

  0

У меня есть ошибка: ./scraper.sh: строка 111: xsel: команда не найдена ./scraper.sh: строка 114: xsel: команда не найдена 19 апр. 162016-04-19 01:57:49

  0

@ 3kstc очевидно, установите xsel. Кроме того, вы можете использовать xclip, но его использование немного отличается. Главный пункт здесь: 1-й вы помещаете вывод в буфер обмена (3 из них в linux), 2-й - вы берете его оттуда и отправляете на stdout. 09 май. 162016-05-09 20:43:39


4

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

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

0

Я получил вокруг этого, когда я делал мой собственный маленький дю:

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