Risposte:
Ecco un modo che utilizza l'espansione dei parametri bash e la sua IFS
variabile speciale.
$ System=('s1' 's2' 's3' 's4 4 4')
$ ( IFS=$'\n'; echo "${System[*]}" )
Usiamo una subshell per evitare di sovrascrivere il valore IFS
nell'ambiente attuale. In quella subshell, modifichiamo quindi il valore in IFS
modo che il primo carattere sia una nuova riga (usando le $'...'
virgolette). Infine, utilizziamo l'espansione dei parametri per stampare il contenuto dell'array come una singola parola; ogni elemento è separato dal primo carattere di IFS
.
Per acquisire in una variabile:
$ var=$( IFS=$'\n'; echo "${System[*]}" )
Se il tuo bash è abbastanza nuovo (4.2 o successivo), puoi (e dovresti) usare ancora printf
con l' -v
opzione:
$ printf -v var "%s\n" "${System[@]}"
In entrambi i casi, potresti non voler inserire la nuova riga finale var
. Per rimuoverlo:
$ var=${var%?} # Remove the final character of var
var=${var%?}
invece? Questa non è un'espressione regolare, quindi .
corrisponderà solo a un carattere punto.
$ IFS=', ' $ echo ${VAR[*]} first second third $ echo "${VAR[*]}" first,second,third
awk -v sep='\n' 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' "${arr[@]}"
o
perl -le 'print join "\n",@ARGV' "${arr[@]}"
o
python -c 'import sys;print "\n".join(sys.argv[1:])' "${arr[@]}"
o
sh -c 'IFS=$'\''\n'\'';echo "$*"' '' "${arr[@]}"
o
lua <(echo 'print(table.concat(arg,"\n"))') "${arr[@]}"
o
tclsh <(echo 'puts [join $argv "\n"]') "${arr[@]}"
o
php -r 'echo implode("\n",array_slice($argv,1));' -- "${arr[@]}"
o
ruby -e 'puts ARGV.join("\n")' "${arr[@]}"
questo è tutto ciò che posso ricordare finora.
Le soluzioni sopra sono praticamente tutto, ma la domanda originale richiede l'output su file:
$ a=(a b c d e)
$ ( IFS=$'\n'; echo "${a[*]}" ) > /tmp/file
$ cat /tmp/file
a
b
c
d
e
$
Note: 1) 'echo' fornisce la nuova riga finale 2) Se questo file verrà nuovamente letto da bash, allora dichiarare -p potrebbe essere la serializzazione desiderata.
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[@]}"
La mia opinione, usando solo i builtin di Bash, senza mutare IFS
:
# $1 separator
# $2… strings
join_strings () {
declare separator="$1";
declare -a args=("${@:2}");
declare result;
printf -v result '%s' "${args[@]/#/$separator}";
printf '%s' "${result:${#separator}}"
}
$ join_strings $'\n' "a b c" "d e f" "g h i"
a b c
d e f
g h i
Puoi anche usare qualsiasi separatore:
$ join_strings '===' "a b c" "d e f" "g h i"
a b c===d e f===g h i
printf
sembra essere l'approccio più efficiente per la creazione di una stringa delimitata da un array:
# create a delimited string; note that printf doesn't put the trailing delimiter
# need to save and restore IFS
# it is prudent to put the whole logic on a single line so as to minimize the risk of future code changes breaking the sequence of saving/restoring of IFS
oldIFS=$IFS; IFS=$'\n'; printf -v var "${arr[*]}"; IFS=$oldIFS
# print string to file; note that the newline is required in the format string because printf wouldn't put a trailing delimiter (which is a good thing)
printf '%s\n' "$var" > file
Un modo ancora più semplice per farlo è:
delim=$'\n'
printf -v var "%s$delim" "${arr[@]}" # create a delimited string
var="${var%$delim}" # remove the trailing delimiter
delim=:
arr=(one two three)
printf -v var "%s$delim" "${arr[@]}" # yields one:two:three:
var="${var%$delim}" # yields one:two_three