シェルスクリプトでsplit

シェルスクリプトで文字列分割と言えばやはりwhile read

while read f1 f2 f3;do
  echo $f1
  echo $f2
done < file.txt

標準入力やファイルから1行ずつ読み込んで、という最もありがちな処理にはこれが1番わかりやすいですね。IFSで区切り文字を変えたりもできます。


しかしある変数、STRに入った文字列を分割するにはどうでしょうか。
readではちょっと難しいです。

STR="aa bb cc"
echo $STR | read f1 f2 f3
echo $f1
# => 何も表示されない

これはパイプがこっそり右側のコマンドをサブシェル起動するためです。
(と昔どこかで読んだんですが$$を表示してみるとPIDはいっしょですね。別の理由かも)
一連の処理をかっこでくくれば回避できなくもないですが、使い勝手悪すぎですね。

STR="aa bb cc"
echo $STR | (
  read f1 f2 f3
  echo $f1
  echo $f2
)


これにはいくつかやりかたがあります。

配列代入

STR="aa bb cc"
foo=($STR)
echo ${foo[0]}
echo ${foo[1]}

特殊変数、$1...に代入

STR="aa bb cc"
set -- $STR
echo $1
echo $2

bash限定、名前つきパイプ

STR="aa bb cc"
read f1 f2 f3 < <( echo $STR )
echo $f1
echo $f2