回答:
これは、bashパラメーター展開とそのIFS
特殊変数を利用する方法です。
$ System=('s1' 's2' 's3' 's4 4 4')
$ ( IFS=$'\n'; echo "${System[*]}" )
サブシェルを使用IFS
して、現在の環境での値の上書きを回避します。そのサブシェルではIFS
、最初の文字が改行になるように値を変更します($'...'
引用符を使用)。最後に、パラメーター展開を使用して、配列の内容を1つの単語として出力します。各要素は、の最初の文字で区切られてい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
var=${var%?}
代わりにすべきではありませんか?これは正規表現ではないため.
、ピリオド文字のみに一致します。
$ 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[@]}"
または
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[@]}"
これで思い出せるのはこれだけです。
上記の解決策はほとんどそれですが、元の質問はファイルへの出力を求めます:
$ a=(a b c d e)
$ ( IFS=$'\n'; echo "${a[*]}" ) > /tmp/file
$ cat /tmp/file
a
b
c
d
e
$
注:1) 'echo'は最後の改行を提供します2)このファイルがbashによって再び読み込まれる場合、declare -pが必要なシリアル化である可能性があります。
私のテイクは、変更せずに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
printf
配列から区切られた文字列を作成するための最も効率的なアプローチのようです:
# 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
これを行うさらに簡単な方法は次のとおりです。
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