read コマンドで入力を読み取る
read コマンドを利用すると標準入力やファイルから入力から1行を読み取ることができます。read コマンドには読み取った結果を代入する変数を指定することができますが、変数を指定しない場合は読み取った行は REPLY 変数に格納されます。
read
echo "REPLY=${REPLY}"
read
echo "REPLY=${REPLY}"
read コマンドに変数を指定した場合、読み取った行は IFS 変数に設定されている区切り文字で単語に分割されて変数に設定されます。
printf 'IFS=%q\n' "${IFS}"
read a b c
echo "a='${a}'"
echo "b='${b}'"
echo "c='${c}'"
余った単語とその間にある区切り文字は、最後に指定した変数に設定されます。
read a b c
echo "a='${a}'"
echo "b='${b}'"
echo "c='${c}'"
IFS 変数の値を変更することで、単語に分割する区切り文字を変更することができます。
IFS=',' read a b c
echo "a='${a}'"
echo "b='${b}'"
echo "c='${c}'"
read コマンドで複数行の入力を読み取る
while ループで read コマンドをループすることで複数行の入力を読み取ることができます。端末上で Ctrl と d キーを同時に押すことで EOF が送信されループは終了します。
while read; do
echo "${REPLY}"
done
ファイルの内容を read コマンドで読み取る
ファイルを標準入力につなぐことで read コマンドでファイルの内容を読み取ることができます。ファイルの最後まで読み取ると while ループは終了します。
# 読み取るファイルを作成する
cat << 'EOF' > './sample.txt'
リンゴ,100
バナナ,120
ミカン,90
EOF
# 標準入力にファイルをつないで read コマンドで読み取る
while IFS=',' read name price; do
echo "${name}は${price}円です"
done <'./sample.txt'
バックスラッシュがエスケープ文字として扱われる点に注意が必要です。無効にするには r オプションを指定します。
# 読み取るファイルを作成する
# 末尾にバックスラッシュがある場合、行継続とみなされる
cat << 'EOF' > './sample.txt'
リンゴ,100\
バナナ\,120
ミカン,90
EOF
echo '# r オプションなし'
while IFS=',' read name price; do
echo "${name}は${price}円です"
done <'./sample.txt'
echo '# r オプションあり'
while IFS=',' read -r name price; do
echo "${name}は${price}円です"
done <'./sample.txt'
コマンドの出力を read コマンドで読み取る
標準入力にコマンドの標準出力をつなぐことで、コマンドの出力を read コマンドで読み取ることができます。
intials=
while read -r word _; do
intials="${intials}${word:0:1}"
done < <(sed --version)
echo "${intials^}"
パイプでつないだ場合はサブシェルで起動されることに注意が必要です。以下のサンプルのように外で宣言された変数を変更することができません。
intials=
# パイプでつないだ場合はサブシェルになるので外で宣言された変数を変更できない
sed --version | while read -r word _; do
intials="${intials}${word:0:1}"
done
echo "${intials^}"
read コマンドのオプション
read コマンドに指定することができるオプションの概要は以下です。
オプション | 説明 |
---|---|
-a aname | 単語を配列変数 aname に読み込んだ単語をインデックス順に代入します。 |
-d delim | 改行ではなく、delim の最初の文字を行の終了を表す文字とて使用します。 |
-e | 標準入力を端末から読み込む場合、readline を使用した編集可能な入力を使います。カーソルの移動や文字の削除、入力の補完などの機能を端末での入力時に利用することができます。 |
-i text | 行を取得するのに readline が使われるとき、入力を開始する前に編集バッファに text が置かれます。 |
-n nchars | 入力行全体が読み込まれるのを待たずに nchars で指定した文字数の文字を読み込むか区切り文字が現れた時点で読み込み結果が戻ります。 |
-N nchars | 入力行全体が読み込まれるのを待たずに nchars で指定した文字数の文字を読み込んだ時点で戻ります。区切り文字を特別扱いしません。 |
-p prompt | 標準入力を端末から読み込む場合に、入力を読み込もうとする前に標準エラー出力に prompt を表示します。 末尾に改行は付きません。 |
-r | バックスラッシュはエスケープ文字として作用しません。 |
-s | 端末に入力が行われても、入力された文字をエコーしません。 |
-t timeout | 入力行全体が timeout 秒以内で読み込まれない場合に失敗の状態を返します。timeout は小数を含めることができます。timeout 秒を超えた場合の終了ステータスは 128 より大きな値になります。 |
-u fd | 入力を fd で指定されたファイルディスクリプターから読み込みます。 |
オプションを指定した動作の確認のため、いくつかサンプルコードを記載します。
read -a 配列変数名 配列に読み込む
read -r -a array
declare -p array
read -n 文字数 指定した文字数か区切り文字が現れるまで読み込む
while read -r -n 5 a b; do
echo "a='${a}',b='${b}'"
done
read -N 文字数 指定した文字数まで読み込む
while read -r -N 5 a b; do
echo "a='${a}',b='${b}'"
done