テキストファイルを 1 行だけ読み込む
read コマンドはユーザからの入力を 1 行取得するために使用できますが、ファイルからの入力を 1 行読み込むのにも使用できます。
#!/bin/bash
read line < input.txt
echo "$line"AAA 100
BBB 200
CCC 300$ ./sample.sh
AAA 100
これだけだとあまり役に立たないので、通常は次のように while ループを組み合わせて、すべての行を読み出します。
テキストファイルから 1 行ずつ読み込む
read コマンドと while ループを組み合わせると、テキストファイルのすべての行を 1 行ずつ処理できます。
#!/bin/bash
while read line; do
echo "$line"
done < input.txtAAA 100
BBB 200
CCC 300$ ./sample.sh
AAA 100
BBB 200
CCC 300
☝️ ワンポイント
echo のパラメータ "$line" をダブルクォートで囲んでいることに注意してください。
こうすることで、1 行分の文字列を、ひとつのパラメータとして渡すことができます。
ダブルクォートで囲まないと、echo AAA 100 のように、2 つのパラメータが渡されたかのように処理されてしまうため、連続するスペースが 1 つのスペースに置き換えられて出力されてしまいます。行頭のスペースが消えてしまうのを防ぐ
例えば、下記のように行頭がインデントされたテキストファイルを読み込むとします。
・カテゴリA
・カテゴリA-1
・カテゴリA-2
・カテゴリB
・カテゴリB-1
・カテゴリB-2このファイルを次のように読み込むと、行頭のスペースが削除されてしまします。
#!/bin/bash
while read line; do
echo "$line"
done < input.txt$ ./sample.sh
・カテゴリA
・カテゴリA-1
・カテゴリA-2
・カテゴリB
・カテゴリB-1
・カテゴリB-2
行頭のスペースをそのまま表示したい場合は、次の例のように、組み込み変数 IFS を空文字にセットしてから処理するようにします。
変更した IFS の値は、最後に行儀よく元の値に戻してあげてください(source コマンドなどでスクリプトを読み込んだときに、呼び出し元シェルの IFS の値が変更されたままになってしまうのを防ぐため)。
#!/bin/bash
old_ifs=$IFS
IFS=''
while read line; do
echo "$line"
done < input.txt
IFS=$old_ifs$ ./sample.sh
・カテゴリA
・カテゴリA-1
・カテゴリA-2
・カテゴリB
・カテゴリB-1
・カテゴリB-2
IFS 特殊変数に関しての詳細は、man bash を参照してください。
IFS は内部的な文字列のセパレート処理に使われるキャラクター群を保持しています。