Como posso ler a entrada do usuário como uma matriz no Bash?

15

Como eu poderia ler a entrada do usuário como uma matriz no bashshell?

moata_u
fonte
Presumo que você queira ler de stdin? Minha resposta também funcionará com execução como cat war_and_peace.txt | ./array_test.sh.
Stefano Palazzo
Ou simplesmente ./array_test.sh < war_and_peace.txt.
Eliah Kagan

Respostas:

14

Aqui está uma maneira de fazer isso:

while read line
do
    my_array=("${my_array[@]}" $line)
done

echo ${my_array[@]}

Se você apenas executá-lo, ele continuará lendo da entrada padrão até você pressionar Ctrl + D (EOF). Depois, as linhas que você inseriu serão inseridas my_array. Alguns podem achar esse código confuso. O corpo do loop basicamente diz my_array = my_array + element.

Algumas peças interessantes de documentação:

Stefano Palazzo
fonte
3
read -ràs vezes é bastante útil / importante ... O link de Stefano para a "página de leitura incorporada" explica seu propósito ... (para impedir a interpretação da barra invertida).
precisa saber é o seguinte
10

Leia-o usando:

read -a arr

E para impressão, use:

for elem in ${arr[@]}
do 
  echo $elem
done
ABcDexter
fonte
4

E um que não recrie a matriz de cada vez (embora exija o bash 3.1 ou mais recente):

array=()
while IFS= read -r -p "Next item (end with an empty line): " line; do
    [[ $line ]] || break  # break if line is empty
    array+=("$line")
done

printf '%s\n' "Items read:"
printf '  «%s»\n' "${array[@]}"

Veja http://mywiki.wooledge.org/BashFAQ/001 para mais informações.

E, como sempre, para evitar erros, leia http://mywiki.wooledge.org/BashGuide e evite os guias tldp como o guia de scripts avançados do bash.

Geirha
fonte
Links agradáveis ​​... Obrigado por apontar o IFSproblema. Sem anulando-lo, 'ler' sripts todos esquerda e à direita espaço em branco ... e, claro, o -rtambém ...
Peter.O
0

Que tal esse one-liner;)

arr=( $(cat -) )
echo ${arr[@]}

Editar:

Em bash,

arr=(val1 val2 ...)

é a maneira de atribuir a uma matriz . Utilizando-o em conjunto com a substituição de comandos, é possível ler em matrizes do pipeline que não é possível usar readpara fazer isso de maneira direta:

echo -e "a\nb" | read -a arr
echo ${arr[@]}

Você descobrirá que ele não readproduz nada devido ao fato de não fazer nada quandostdin é um tubo, uma vez que um pipeline pode ser executado em um subshell para que a variável possa não ser utilizável.

Usando o caminho sugerido por esta resposta:

arr=(`echo -e "a\nb"`)
echo ${arr[@]}

Ele fornece a buma maneira mais simples e direta do que qualquer solução alternativa fornecida pelas respostas dos valores Read em uma variável de shell de um pipe e na leitura do bash depois que um pipe não está definindo valores .

Quark
fonte
você testou?
Cmak.fr 9/03/19
@ cmak.fr sim ele funciona para mim
Quark
@ Melebius Anexei uma explicação e a vantagem deste one-liner.
JiaHao Xu 19/08/19