web-dev-qa-db-ja.com

bash配列変数を改行で区切られた文字列に変換するにはどうすればいいですか?

各要素を新しい行に入れて、ファイルにbash配列変数を書き出します。 forループでこれを行うことができますが、\nで要素を結合するための別の(よりきれいな)方法はありますか?

48
ACyclic

これはbashパラメータ展開とそのIFS特殊変数を利用する方法です。

$ System=('s1' 's2' 's3' 's4 4 4')
$ ( IFS=$'\n'; echo "${System[*]}" )

現在の環境でIFSの値が上書きされないようにするためにサブシェルを使用します。そのサブシェルで、最初の文字が改行になるようにIFSの値を変更します($'...'クォートを使用)。最後に、パラメータ展開を使用して、配列の内容を単一のWordとして出力します。各要素はIFSの最初の文字で区切られています。

変数にキャプチャするには:

$ var=$( IFS=$'\n'; echo "${System[*]}" )

あなたのbashが十分新しい(4.2以降)なら、あなたはまだprintf-vオプションと一緒に使うことができます(そしてそうすべきです):

$ printf -v var "%s\n" "${System[@]}"

どちらの場合でも、varの最後の改行は望まないかもしれません。それを削除するには:

$ var=${var%?}    # Remove the final character of var
54
chepner

printfを使用して各配列項目をそれぞれ独自の行に印刷することができます。

 $ System=('s1' 's2' 's3' 's4 4 4')
 $ printf "%s\n"  "${System[@]}"
s1
s2
s3
s4 4 4
26
rush
awk -v sep='\n' 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' "${arr[@]}"

または

Perl -le 'print join "\n",@ARGV' "${arr[@]}"

または

python -c 'import sys;print "\n".join(sys.argv[1:])' "${arr[@]}"

または

sh -c 'IFS=$'\''\n'\'';echo "$*"' '' "${arr[@]}"

または

lua <(echo 'print(table.concat(arg,"\n"))') "${arr[@]}"

または

tclsh <(echo 'puts [join $argv "\n"]') "${arr[@]}"

または

php -r 'echo implode("\n",array_slice($argv,1));' -- "${arr[@]}"

または

Ruby -e 'puts ARGV.join("\n")' "${arr[@]}"

これまでに思い出したことがすべてです。

6
Meow

上記の解決策はほとんど問題ありませんが、元の質問ではファイルへの出力が求められます。

$ a=(a b c d e)
$ ( IFS=$'\n'; echo "${a[*]}" ) > /tmp/file
$ cat /tmp/file
a
b
c
d
e
$

注:1) 'echo'は最後の改行を提供します。2)このファイルがbashによって再度読み込まれるだけの場合は、-pを宣言してシリアライゼーションを実行します。

2
Brian Chrisman

forを使う:

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

history;を使う値に!が含まれているとこれが失敗することに注意してください。

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

basename;を使う値に/が含まれているとこれが失敗することに注意してください。

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

shuf;を使う結果が順番どおりにならない可能性があることに注意してください。

shuf -e "${alpha[@]}"
2
Steven Penny

My take 、Bashビルトインのみを使用し、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

任意のセパレータを使用することもできます:

$ join_strings '===' "a b c" "d e f" "g h i"
a b c===d e f===g h i
0
jcayzac