Enquanto loop lê múltiplas linhas de um grep

3

Estou escrevendo um script no AIX 5.3 que percorrerá a saída de um df e verificará cada volume em relação a outro arquivo de configuração. Se o volume aparecer no arquivo de configuração, ele definirá um sinalizador que será necessário posteriormente no script. Se meu arquivo de configuração tiver apenas uma única coluna e eu usar um for loop, isso funciona perfeitamente. Meu problema, no entanto, é que, se eu usar um loop while read para preencher mais de uma variável por linha, quaisquer variáveis que eu definir entre o while e o done serão descartadas.

Por exemplo, supondo que o conteúdo de /netapp/conf/ExcludeFile.conf seja um monte de linhas contendo dois campos cada:

volName="myVolume"
utilization=70
thresholdFlag=0

grep volName /netapp/conf/ExcludeFile.conf | while read vol threshold; do
    if [ $utilization -ge $threshold ] ; then
        thresholdFlag=1
    fi
done

echo "$thresholdFlag"

Neste exemplo, thresholdFlag sempre será 0, mesmo que o volume apareça no arquivo e sua utilização seja maior que o limite. Eu poderia ter adicionado um echo "setting thresholdFlag to 1" lá, ver o eco, e ainda vai ecoar um 0 no final.

Existe uma maneira limpa de fazer isso? Eu acho que o meu loop while está sendo feito em um subshell, e as alterações que eu faço para variáveis estão sendo feitas para variáveis locais que são descartadas após o done .

    
por Basil 11.10.2012 / 22:24

2 respostas

4

Zoredache apontou isso para mim no chat, e poige mencionou isso em sua resposta: esse problema pode ser resolvido com um subshell.

Quando eu tive que mudar de um loop for que lia uma única variável do meu grep de uma vez para um while read var1 var2 loop que me permitia ler em múltiplas variáveis, eu era capaz de segurar variáveis temporárias I manipulado dentro do loop while usando parênteses para definir um subshell explícito. Aqui está um exemplo:

sum=0

grep volume configfile | head -n1 | (while read var1 var2; do
  let sum=var1+var2
done

echo "The sum is $sum.")

Sem os parênteses, você sempre ecoará uma soma de 0. Com eles, você irá ecoar a soma dos dois primeiros valores na primeira linha correspondente do seu grep.

Além disso, como Poige aponta em outra resposta, você pode usar um subshell para preencher uma variável no escopo como esta:

var=$( cat file | while read a b; do
    sum=a+b
    echo "$sum"
done)

echo "$var"

Nesse caso, o valor de var que você faz eco no final seria a última soma que você calculou no loop, mesmo que a soma tenha sido destruída no final da sub-camada.

    
por 12.10.2012 / 16:07
-2

Pelo menos duas maneiras - retorne o código de erro e verifique-o ou envolva o código do sub-shell:

Res=$(cat /etc/hosts | while read h _rest; do
    [ "$h" = 'fe00::0' ] && echo 'Found'
done
)
echo $Res
    
por 11.10.2012 / 22:40