リードって便利だなって聞いてたけど。。。真夜中のシェルの調べ

今回はシェルについて(bash)

とりあえずなんとなくシェルを書いていてつまづいたことがあった。
そう、readコマンドについて、である。

今回はまったケースは
・while readのループの中で新しくreadコマンドでキーボード入力をしたかったけど
実際にはwhile readで読み込んだ行の次の行が読み込まれてしまう

という現象。

まずは事象について

test.sh

#!/bin/bash

file_name=name.lst
cat ${file_name} | while read line; do
  echo "Well..."
  echo "Are you ${line}? [y/n]"
  read answer
  if [[ ${answer} = y ]]; then
    echo "Yes, you are completely ${line}."
    echo "Have a good time."
    exit 1
  fi
  echo "Oh, so sorry..."
done
if [[ $? -eq 1 ]]; then
  exit 1
fi
echo "I don't know you."
exit 0

name.lst

footaro
bartaro
hogeko

これの実行結果は例えば次のようになる。

Well...
Are you footaro? [y/n]
Oh, so sorry...
Well...
Are you hogeko? [y/n]
Oh, so sorry...
I don't know you.

キーボード入力したかったのに勝手に進んで終了してしまった。私hogekoなのに。。。
っていう悲しい結果になる(bartaroは!?)


ぐぐったところ、キーボードからの入力にしたい場合には
read answer

read answer < /dev/tty

とすればよいらしい。
実行結果

Well...
Are you footaro? [y/n]
n
Oh, so sorry...
Well...
Are you bartaro? [y/n]
n
Oh, so sorry...
Well...
Are you hogeko? [y/n]
y
Yes, you are completely hogeko.
Have a good time.

よしよし。hogekoって言えたぞ。


Tips
ちなみにwhileループの中でexitを用いてもループを抜けるだけでシェル自体は終了できないので
ループを抜けた後に判定する必要もあるらしい(ぐぐった)

今回ぐぐったサイト

シェルスクリプトでパイプからの入力とキーボード入力を区別する - rcmdnk’s blog

bashはwhile内の処理が子プロセス扱いになる - Alligator Swamp