Imprimir uma matriz em um arquivo com cada elemento da matriz em uma nova linha no bash

13

Estou tentando o conteúdo de uma matriz em um arquivo com cada elemento da matriz em uma nova linha no arquivo.

IFS=$'\n'   
echo "${mtches[@]}" > sample1.txt 


O conteúdo de mtches é "qwe" e "asd". Mas o sample1.txtarquivo contém qwe asdem uma única linha. Por que não está levando em consideração o valor do IFS?

Ashwin
fonte

Respostas:

16

Você deve usar em printfvez deecho :

printf "%s\n" "${mtches[@]}"

Se mtchesestiver vazio, isso ainda produziria uma linha vazia. Para explicar isso:

{ [ "${#mtches[@]}" -eq 0 ] || printf '%s\n' "${mtches[@]}"; } > file

Em bash(e também em shells POSIX), você geralmente usa a matriz Parâmetros Posicionais em "$@"vez de "$*", a menos que tenha um motivo especial. Isso também é verdade em shells que suportam matrizes regulares, do man bash - section Matrizes :

Qualquer elemento de uma matriz pode ser referenciado usando $ {name [subscript]}. Os colchetes são necessários para evitar conflitos com os operadores de expansão de nome de arquivo do shell. Se o subscrito for '@' ou '*', a palavra se expandirá para todos os membros do nome da matriz. Esses subscritos diferem apenas quando a palavra aparece entre aspas duplas. Se a palavra estiver entre aspas duplas, $ {name [*]} será expandida para uma única palavra com o valor de cada membro da matriz separado pelo primeiro caractere da variável IFS, e $ {name [@]} expandirá cada elemento do nome para uma palavra separada. Quando não há membros da matriz, $ {name [@]} se expande para nada. Se a expansão entre aspas ocorrer em uma palavra, a expansão do primeiro parâmetro será associada à parte inicial da palavra original e a expansão do último parâmetro será associada à última parte da palavra original.

Use somente "${array[*]}"quando desejar associar todos os elementos da matriz a uma sequência.

cuonglm
fonte
Como isso faz diferença?
Ashwin
7

Você deseja usar em seu ${mtches[*]}lugar.

Quando você usa "${mtches[@]}", não importa qual é o valor $IFS, o bash dividirá a matriz em vários argumentos. O que você deseja é um único argumento com cada elemento do array associado \n. ${mtches[*]}realiza isso.

Também como forma temporária de configuração $IFS, você pode:

( IFS=$'\n'; echo "${mtches[*]}" > sample1.txt )

Então você não precisa se preocupar em configurá-lo de volta.

Patrick
fonte
pubs.opengroup.org/onlinepubs/9699919799/utilities/… <- referência POSIX (isso não se aplica apenas ao bash).
Mat
Ou use printf...
jasonwryan
2

Usando para :

for each in "${alpha[@]}"
do
  echo "$each"
done

Usando história ; observe que isso falhará se seus valores contiverem !:

history -p "${alpha[@]}"

Usando o basename ; observe que isso falhará se seus valores contiverem /:

basename -a "${alpha[@]}"

Usando shuf ; observe que os resultados podem não sair em ordem:

shuf -e "${alpha[@]}"
Steven Penny
fonte
1
for ENTRY in ${ARRAY[@]}; do
    echo $ENTRY
done > outfile

Bom e legível e não significa mexer com o IFS. Isso também significa que você pode personalizar o manuseio de cada linha.

steveayre
fonte
1
Mas, por mais errado que você esteja usando, echonão pode ser usado para conteúdo arbitrário e esqueceu de citar suas variáveis . Uma versão um pouco melhor já foi publicada por StevenPenny
Stéphane Chazelas