Por que a matriz está vazia após o loop while? [duplicado]

2

Eu tento inicializar um array no bash-4.2 da seguinte maneira:

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[@]}"

O que está errado, por que recebo array vazio após o término do loop?

    
por Dimaf 28.03.2016 / 21:50

3 respostas

6

Seu problema é que em um pipeline ( command1 | command2 | command3 ... ) os comandos são executados em subshells. Variáveis não são compartilhadas entre subshells ou entre subshells e o shell principal. O ring no loop while é diferente do ring no shell principal.

Uma maneira de superar isso é usar a substituição de processos:

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

A sintaxe <(command) é chamada de substituição do processo e redirecionará a saída do comando para um canal nomeado. Que é então redirecionado com o familiar < como se fosse um arquivo. Quando você usa < , não há subshell, então a variável ring será definida.

Observe que há um comando interno do shell para preencher uma matriz das linhas de um arquivo:

mapfile -t ring < <(ls -las | tail -n +4)
    
por 28.03.2016 / 22:38
2

Isso deve funcionar bem:

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

Fonte: link

    
por 28.03.2016 / 22:50
0

A razão é que o loop é executado em um subshell devido ao fato de ser canalizado. O Subshell usa uma cópia do ambiente de shell pai e não o repassa quando a subshell é encerrada.

para o bash você pode usar a solução alternativa de agrupamento de comandos, sem chaves adicionadas

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