2011-09-12 4 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} 

Las instrucciones de eco fuera del ciclo no muestran las variables esperadas. ¿Cómo debo hacer que los contenidos de la variable se propaguen fuera del ciclo?Bash: propagar el valor de la variable al exterior del ciclo

+6

Tenga en cuenta que el bucle 'while' se ejecuta en un proceso separado, esta es la razón por la que no ve las variables modificadas. –

+1

¿Usar sustitución de proceso? –

Respuesta

19

El problema es la tubería, no el lazo. Pruébelo de esta manera

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} 

También debe declarar previamente los globales para mayor claridad, como se muestra arriba.

Las tuberías se ejecutan en una subcamada, como señala Blagovest en su comentario. El uso de process substitution instead (esta es la sintaxis < <(commands)) mantiene todo en el mismo proceso, por lo que son posibles cambios en las variables globales.

Por cierto, su tubería se podría mejorar, así

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

Uno menos invocación de grep que preocuparse.

+0

Gran explicación. +1 –

+0

gracias por la explicación :-) – masuch

+0

En bash 3.x, la última línea del ciclo debería ser como 'done <<< \' comandos \ '' – Ida

3

Esta un poco by-pass a su pregunta (y que es una buena pregunta), pero se puede lograr los mismos resultados utilizando simplemente:

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

La construcción ($(cmd)) inicializa una matriz de bash utilizando la salida del comando dentro .

[[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 

y se puede obtener el número de elementos que utilizan ${#_constr[*]}.

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

Muchas gracias :-) – masuch

+0

Esta es realmente la manera correcta de hacerlo. No tenía una caja Debian para probar o hubiera sugerido lo mismo. – Sorpigal

0

Como alternativa, puede mover las declaraciones de eco dentro de la subcapa:

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 de la inserción del paréntesis para definir explícitamente en el que el subnivel comienza y termina.

Cuestiones relacionadas