文字列を分割するサンプルスクリプトを作成しましたが、期待どおりに機能しません。
#!/bin/bash
IN="One-XX-X-17.0.0"
IFS='-' read -r -a ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
echo "Element:$i"
done
#split 17.0.0 into NUM
IFS='.' read -a array <<<${ADDR[3]};
for element in "${array[@]}"
do
echo "Num:$element"
done
- 実際の出力
One XX X 17.0.0 17 0 0
- しかし、私の予想結果は次のとおりです。
One XX X 17.0.0 17 0 0
ベストアンサー1
以前のバージョンでは、bash
後で変数を引用する必要がありました<<<
。この問題は4.4で修正されました。以前のバージョンでは、変数はIFSで分割され、結果の単語がリダイレクトを<<<
構成する一時ファイルに格納される前に空間的にリンクされていました。
4.2以前では、read
または同じ組み込み関数をリダイレクトするときに、分割command
がその組み込み関数のIFSも使用しました(4.3ではこの問題は修正されました)。
$ 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"
任意の文字列を分割するには、分割+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
空の要素に分割します。
または、適切な分割演算子でシェルを使用してください。
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