古いバージョンでbashは、後に変数を引用する必要がありました<<<。これは4.4で修正されました。古いバージョンでは、変数はIFSで分割され、結果の単語はスペースで結合されてから、その<<<リダイレクトを構成する一時ファイルに格納されていました。
以下のような組み込みコマンドをリダイレクトする4.2と前に、中readまたはcommand分割が偶数(4.3という固定)その組み込み用のIFSを取るだろうと、:
$ bash-4.2 -c 'a=a.b.c.d; IFS=. read x <<< $a; echo "$x"'
a b c d
$ bash-4.2 -c 'a=a.b.c.d; IFS=. cat <<< $a'
a.b.c.d
$ bash-4.2 -c 'a=a.b.c.d; IFS=. command cat <<< $a'
a b c d
4.3で修正されたもの:
$ bash-4.3 -c 'a=a.b.c.d; IFS=. read x <<< $a; echo "$x"'
a.b.c.d
しかし、$aそこでも単語分割が行われます。
$ bash-4.3 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a b c d
4.4では:
$ bash-4.4 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a.b.c.d
古いバージョンへの移植性のために、変数を引用してください(または、そもそもzshそれ<<<がどこから来て、その問題がないところを使用してください)
$ bash-any-version -c 'a=a.b.c.d; IFS=.; read x <<< "$a"; echo "$x"'
a.b.c.d
文字列を分割するこのアプローチは、改行文字を含まない文字列に対してのみ機能することに注意してください。また、それは注意してくださいa..b.c.に分割されるだろう"a"、""、"b"、"c"(なし最後の要素を空に)。
任意の文字列を分割するには、代わりにsplit + glob演算子を使用できます(これにより、標準になり、変数の内容を一時ファイルに保存することを回避できます<<<)。
var='a.new
line..b.c.'
set -o noglob # disable glob
IFS=.
set -- $var'' # split+glob
for i do
printf 'item: <%s>\n' "$i"
done
または:
array=($var'') # in shells with array support
''もしあれば後続の空の要素を保持することです。また、空$varを1つの空の要素に分割します。
または、適切な分割演算子を使用してシェルを使用します。
zsh:
array=(${(s:.:)var} # removes empty elements
array=("${(@s:.:)var}") # preserves empty elements
rc:
array = ``(.){printf %s $var} # removes empty elements
fish
set array (string split . -- $var) # not for multiline $var