¿Por qué la matriz está vacía después del ciclo while?

Intento inicializar una matriz en bash-4.2 de la siguiente manera:

ring=() ls -las | tail -n +4 | while read line > do > ring+=("$line") > echo ${ring[-1]} > done 3924 -rw-r--r-- 1 username group 4015716 Mar 23 15:14 script.jar 4 -rw-r--r-- 1 username group 9 Feb 29 12:40 rec.lst 5541 -rw-r--r-- 1 username group 5674226917 Mar 28 15:25 debug.out 8 -rw-r--r-- 1 username group 6135 Mar 25 12:16 script.class 8 -rw-r--r-- 1 username group 6377 Mar 25 11:57 script.java 8 -rwxr-xr-x 1 username group 4930 Mar 8 15:21 script-0.0.0.sh 8 -rwxr-xr-x 1 username group 6361 Mar 28 15:27 script-0.0.1.sh echo ${ring[0]} echo "${ring[0]}" echo "${ring[@]}" 

¿Qué pasa, por qué obtengo una matriz vacía después del final del ciclo?

Su problema es que en una canalización ( command1 | command2 | command3 ... ) los commands se command1 | command2 | command3 ... . Las variables no se comparten entre subcapas o entre subcapas y el shell principal. El ring en el ciclo while es diferente del ring en el shell principal.

Una forma de superar esto es usar la sustitución de processs:

 while read line; do ring+=("$line"); echo ${ring[-1]}; done < <(ls -las|tail -n +4) 

La syntax <(command) se denomina sustitución de process y networkingireccionará la salida del command a una tubería con nombre. Que luego se networkingirige con el familiar < como si fuera un file. Cuando usa < , no hay subshell, entonces se establecerá la variable de ring .

Tenga en count que hay un command de shell incorporado para completar una matriz desde las líneas de un file:

 mapfile -t ring < <(ls -las | tail -n +4) 

Esto debería funcionar bien:

 ring=() while read line do ring+=("$line") echo ${ring[-1]} done < <(ls -las | tail -n +4) 

Fuente: http://wiki.bash-hackers.org/syntax/arrays

El motivo es cuando el ciclo se ejecuta en una subcadena debido al hecho de que está canalizado. Subshell utiliza una copy del entorno del shell primario y no lo restituye cuando se cierra el subshell.

para bash, puede usar una solución de agrupación de commands, tenga en count que se agregaron corchetes

 ls -las | tail -n +4 | { while read line; do ring+=("$line"); echo ${ring[-1]}; done; echo ${ring[0]}; }