Stampa un array su un file con ogni elemento dell'array in una nuova riga in bash


13

Sto provando il contenuto di un array in un file con ogni elemento dell'array in una nuova riga nel file.

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


Il contenuto di mtches è "qwe" e "asd". Ma il sample1.txtfile contiene qwe asdin una sola riga. Perché non sta prendendo in considerazione il valore IFS?

Risposte:


17

Dovresti usare printfinvece diecho :

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

Se mtchesè vuoto, verrà comunque emessa una riga vuota. Per tener conto di ciò:

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

Nelle bash(e anche nelle shell POSIX), spesso si utilizza l' array Parametri posizionali come "$@"invece di "$*", a meno che non si abbia un motivo speciale. Questo è vero anche nelle shell che supportano array regolari, da man bash - section Arrays :

È possibile fare riferimento a qualsiasi elemento di un array usando $ {name [pedice]}. Le parentesi graffe sono necessarie per evitare conflitti con gli operatori di espansione del nome file della shell. Se il pedice è '@' o '*', la parola si espande a tutti i membri del nome dell'array. Questi pedici differiscono solo quando la parola appare tra virgolette. Se la parola è racchiusa tra virgolette doppie, $ {name [*]} si espande in una singola parola con il valore di ciascun membro dell'array separato dal primo carattere della variabile IFS e $ {name [@]} espande ogni elemento del nome a una parola separata. Quando non ci sono membri dell'array, $ {name [@]} si espande in nulla. Se l'espansione tra virgolette doppie si verifica all'interno di una parola, l'espansione del primo parametro viene unita alla parte iniziale della parola originale e l'espansione dell'ultimo parametro viene unita all'ultima parte della parola originale.

Utilizzare solo "${array[*]}"quando si desidera unire tutti gli elementi dell'array a una stringa.


In che modo fa la differenza?
Ashwin,


7

Vuoi usare ${mtches[*]}invece.

Quando lo usi "${mtches[@]}", non importa quale sia il valore di $IFS, bash suddividerà l'array in più argomenti. Quello che vuoi è un singolo argomento con ogni elemento dell'array unito da \n. ${mtches[*]}compie questo.

Inoltre, come modo temporaneo di impostazione $IFS, puoi fare:

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

Quindi non devi preoccuparti di ripristinarlo.


pubs.opengroup.org/onlinepubs/9699919799/utilities/… <- Riferimento POSIX (questo non si applica solo a bash).
Mat

O usa printf...
jasonwryan,

2

Utilizzando per :

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

Utilizzando la cronologia ; nota che questo fallirà se i tuoi valori contengono !:

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

Utilizzando basename ; nota che questo fallirà se i tuoi valori contengono /:

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

Usando shuf ; si noti che i risultati potrebbero non essere pubblicati in ordine:

shuf -e "${alpha[@]}"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.