Lendo stdin em uma matriz bash

6

Eu quero realizar o equivalente a:

list=()
while read i; do
  list+=("$i")
done <<<"$input"

com

IFS=$'\n' read -r -a list <<<"$input"

O que estou fazendo de errado?

input='/bin/ls /'

IFS=$'\n' read -r -a list <<<"$input"

for i in "${list[@]}"; do
  echo "$i"
done

Isso deve imprimir uma listagem de / , mas estou recebendo apenas o primeiro item.

    
por PSkocik 23.11.2015 / 13:25

3 respostas

9

Você deve usar o arquivo de mapas (ou seu sinônimo readarray , que foi introduzido em bash 4.0 ):

mapfile -t list <<<"$input"

Uma leitura só funciona com uma linha, não com todo o padrão entrada.

read -a list preenche o conteúdo da primeira linha do padrão na matriz list . No seu caso, você tem bin como o único elemento na lista de array.

    
por 23.11.2015 / 13:38
4

Solução para Bash versão 3 (e 4)

Por acaso, eu estava logado em uma caixa do CentOS 5 executando o Bash 3 e estava trabalhando em uma solução. Eu já inventei a resposta do cuonglm, mas achei que poderia postar a solução que eu criei que funcionasse com o Bash 3 (e 4). Eu testei com um arquivo que tinha um espaço em seu nome e outro que começa com - .

Em vez de

IFS=$'\n' read -r -a list <<<"$input"

simplesmente use a substituição de comando para criar e preencher a matriz:

IFS=$'\n' # split on newline only
set -f    # disable globbing
list=($(printf "%s" "$input"))

Observação: isso não funcionará com nomes de arquivos com novas linhas em seus nomes.

    
por 23.11.2015 / 14:47
3

para bash versões que não suportam mapfile

IFS=$'\n' read -ra list -d '' <<< "$input"

deve fazer o truque

    
por 23.11.2015 / 15:13

Tags