Escopo variável de bash

Por favor, explique-me porque a última declaração “echo” está em branco? Espero que tenha sido incrementado no loop while para um valor de 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 

Eu tentei usar a seguinte instrução em vez do método ++ XCODE

 XCODE=`expr $XCODE + 1` 

e também não será impresso fora da declaração while. Acho que estou perdendo alguma coisa sobre o escopo da variável aqui, mas a página do manual não está mostrando isso para mim.

Como você está trabalhando no loop while, um sub shell é criado para executar o loop while. Agora, esse processo filho possui sua própria cópia do ambiente e não pode passar nenhuma variável de volta para seu pai (como em qualquer processo unix).

Portanto, você precisará reestruturar-se para não entrar no loop. Como alternativa, você poderia executar uma function por exemplo e ecoar o valor que deseja retornar do subprocess.

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

O problema é que os processos juntos com um pipe são executados em subshells (e, portanto, possuem seu próprio ambiente). O que quer que aconteça durante o while não afeta nada fora do tubo.

Seu exemplo específico pode ser resolvido reescrevendo o pipe para

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

ou talvez

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

Isso deve funcionar também (porque echo e while estão no mesmo subshell):

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

Mais uma opção:

 #!/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: aqui, xsel é um requisito (instalá-lo). Como alternativa, você pode usar xclip: xclip -i -selection clipboard vez de xsel -i -p

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

veja se essas mudanças ajudam

Outra opção é produzir os resultados em um arquivo a partir do subshell e depois lê-lo no shell pai. algo como

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

Eu fiquei por perto quando eu estava fazendo meu próprio 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" ) 

O ponto é que eu faço um subshell com () contendo minha variável SUM e while, mas cano para o todo () ao invés do próprio while, o que evita o gotcha.