2011-09-12 10 views
11
dpkg --list |grep linux-image |grep "ii " | while read line 
do 
    arr=(${line}) 
    let i=i+1 
    _constr+="${arr[2]} " 
done 
echo $i 
echo ${_constr} 

Le istruzioni di eco all'esterno del ciclo non visualizzano le variabili previste. Come si deve propagare il contenuto della variabile all'esterno del loop?Bash - propagazione del valore della variabile all'esterno del loop

+6

Ricordare che il ciclo 'while' viene eseguito in un processo separato, questo è il motivo per cui non si vedono le variabili modificate. –

+1

Utilizzare la sostituzione del processo? –

risposta

19

Il problema è il tubo, non il circuito. Provalo in questo modo

let i=0 
declare -a arr 

while read -r line ; do 
    arr=(${line}) 
    let i=i+1 
    _constr+="${arr[2]} " 
done < <(dpkg --list |grep linux-image |grep "ii ") 

echo $i 
echo ${_constr} 

È necessario anche pre-dichiarare i globali per chiarezza, come mostrato sopra.

I pipe vengono eseguiti in una subshell, come notato da Blagovest nel suo commento. L'utilizzo di process substitution instead (questa è la sintassi < <(commands)) mantiene tutto nello stesso processo, pertanto sono possibili modifiche alle variabili globali.

Per inciso, la pipeline potrebbe essere migliorata così

dpkg --list |grep '^ii.*linux-image' 

Uno meno invocazione di grep di cui preoccuparsi.

+0

Ottima spiegazione. +1 –

+0

grazie per la spiegazione :-) – masuch

+0

In bash 3.x, l'ultima riga del ciclo dovrebbe essere come 'done <<< \' commands \ '' – Ida

3

questo un po 'di by-pass la tua domanda (ed è una buona domanda), ma è possibile ottenere gli stessi risultati utilizzando semplicemente:

_constr=($(dpkg --list | awk '/^ii.*linux-image/{print $2}')) 

Il ($(cmd)) costrutto inizializza un array di bash utilizzando l'output del comando all'interno .

[[email protected]]$ echo ${_constr[*]} 
linux-image-2.6.35-22-generic linux-image-2.6.35-28-generic linux-image-generic 
[[email protected]]$ echo ${_constr[2]} 
linux-image-generic 

e si può ottenere il numero di elementi che utilizzano ${#_constr[*]}.

[[email protected]]$ echo ${#_constr[*]} 
3 
+0

Grazie mille :-) – masuch

+0

Questo è davvero il modo giusto per farlo. Non avevo una scatola Debian con cui testare o avrei suggerito la stessa cosa. – Sorpigal

0

In alternativa, è possibile spostare le dichiarazioni di eco all'interno della subshell:

dpkg --list |grep linux-image |grep "ii " | (
    let i=0 
    declare -a arr 

    while read line 
    do 
    arr=(${line}) 
    let i=i+1 
    _constr+="${arr[2]} " 
    done 
    echo $i 
    echo ${_constr} 
) 

nota l'inserimento della parentesi per definire in modo esplicito dove il subshell inizia e finisce.

Problemi correlati