まくまくLinux/Shellノート
シェルスクリプト: テキストファイルを読み込む
2012-11-05
シェルスクリプトの while 構文と、read コマンドを組み合わせて使用すると、テキストファイルの内容を一行ずつ処理できます。

テキストファイルを一行だけ読み込む

read コマンドは、ユーザからの入力を一行取得するために使用できますが、ファイルからの入力を一行読み込むのにも使用できます。

sample.sh (input.txt の内容を一行だけ読み込む)

#!/bin/bash

read line < input.txt
echo "$line"

input.txt(入力データ)

AAA   100
BBB   200
CCC   300

実行結果

$ ./sample.sh
AAA   100

テキストファイルから一行ずつ読み込む

read コマンドと while ループを組み合わせると、テキストファイルのすべての行を一行ずつ処理できます。

sample.sh (input.txt の内容を一行ずつ読み込む)

#!/bin/sh

while read line; do
  echo "$line"
done < input.txt

input.txt(入力データ)

AAA   100
BBB   200
CCC   300

実行結果

$ ./sample.sh
AAA   100
BBB   200
CCC   300
echo のパラメータ "$line" をダブルクォートで囲んでいることに注意してください。こうすることで、一行分の文字列を、ひとつのパラメータとして渡すことができます。ダブルクォートで囲まないと、echo AAA 100 のように、2つのパラメータが渡されたかのように処理されてしまうため、連続するスペースが1つのスペースに置き換えられて出力されてしまいます。

行頭のスペースが消えてしまうのを防ぐ

例えば、下記のように行頭がインデントされたテキストファイルを読み込むとします。

input.txt(入力データ)

・カテゴリA
    ・カテゴリA-1
    ・カテゴリA-2
・カテゴリB
    ・カテゴリB-1
    ・カテゴリB-2

このファイルを次のように読み込むと、行頭のスペースが削除されてしまします。

#!/bin/sh

while read line; do
  echo "$line"
done < input.txt

出力結果

・カテゴリA
・カテゴリA-1
・カテゴリA-2
・カテゴリB
・カテゴリB-1
・カテゴリB-2

行頭のスペースをそのまま表示したい場合は、次の例のように、組み込み変数 IFS を空文字にセットしてから処理するようにします。 変更した IFS の値は、最後に行儀よく元の値に戻してあげてください(source コマンドなどでスクリプトを読み込んだときに、呼び出し元シェルの IFS の値が変更されたままになってしまうのを防ぐため)。

#!/bin/sh

old_ifs=$IFS
IFS=''

while read line; do
  echo "$line"
done < input.txt

IFS=$old_ifs

出力結果

・カテゴリA
    ・カテゴリA-1
    ・カテゴリA-2
・カテゴリB
    ・カテゴリB-1
    ・カテゴリB-2

IFS 特殊変数に関しての詳細は、man bash を参照してください。 IFS は内部的な文字列のセパレート処理に使われるキャラクター群を保持しています。

2012-11-05