テキスト読込みreadとwhile文がうまく動かない!!!
シェルスクリプトで遊んでいたのですが、下記の問題に当たってしまいました・・・。
100
200
300
400
while read line; do
echo $line
read -p "--> 確認してください。【Enter】" stop
done < /work/check.txt
100
300
あれ、処理が止まらずに一気に実行されてしまっている!!?
しかも値が足りない!!!
試しに【 read -p "--> 確認してください。【Enter】 stop 】を抜いてみて実行してみた。
while read line; do
echo $line
done < /work/check.txt
100
200
300
400
値は、想定通り出力されている。
てことは、やはり抜いた部分がおかしい・・・?
今度は、下記のようにしてみる。
while read line; do
echo $line
read -p "--> 確認してください。【Enter】" stop
echo "確認:$stop"
done < /work/check.txt
100
確認:200
300
確認:400
【 stop 】のやつが、値を拾ってしまっているやないかい!!
なぜこういうことが起こったか・・・?
そもそもreadコマンドって何だっけ・・・?
readコマンド
標準入力からの入力をシェル変数に読み込むコマンド
書式:read 変数 [変数 変数...]
~~参考リンク~~
read - 標準入力から変数に代入する
[シェルスクリプト] readコマンドについて整理してみた
どうやら readコマンド で複数の変数を指定するパターンと同じことが起きているようだ。
[root]# read line stop
test1 test2
[root]# echo $line
test1
[root]# echo $stop
test2
別々でwhile文で指定した【read line】とその中で指定した【read stop】は、別物として扱われると思ってたのだが、一つの【read line stop】として扱われてしまうのですね・・・。
while read line; do
echo $line
read -p "--> 確認してください。【Enter】" stop
done < /work/check.txt
これをどのようにして想定通りの結果にしようか?
気持ち的には、下記のようにしたい!!!
妥協して、sleepコマンドを使って数秒待機させるか・・・?
もう少し方法を探してみたいと思います。
100
--> 確認してください。【Enter】
200
--> 確認してください。【Enter】
300
--> 確認してください。【Enter】
400
--> 確認してください。【Enter】
解決しました!
まず下記の認識は、間違っていました。
別々でwhile文で指定した【read line】とその中で指定した【read stop】は、別物として扱われると思ってたのだが、一つの【read line stop】として扱われてしまうのですね・・・。
@angel_p_57 さんによると、今回うまくいかなかった原因は、
While文で使用していた2つの【readコマンド】でFD(ファイルディスクリプタ)がバッティングし、値が交互にそれぞれの変数に代入されてしまったから。とのこと!
そもそもFD(ファイルディスクリプタ)って何だっけ?
そういえば、LPIC1勉強してた時にちらっと出てきてたなー・・・。
FD(ファイルディスクリプタ)
プログラムがアクセスするファイルや標準入出力などをOSが識別するために用いる識別子のこと
またFDを指定していない read コマンドは、標準入力 ( FD:0 ) を使用するとのこと。
---- 上記の情報を踏まえたうえで解決するとしたら ----
① readコマンドで使用するDFを指定する 【by @angel_p_57 さんより】
--> 指定する方法 オプション(-u)を使用する
100
200
300
400
# FDを10に指定(使用可能FD範囲で、0-2以外なら何でもOK?)
# 内部の read は、デフォルトでOK!
while read -u 10 line; do
echo $line
read -p "--> 確認してください。【Enter】" stop
done 10< /work/check.txt
100
--> 確認してください。【Enter】
200
--> 確認してください。【Enter】
300
--> 確認してください。【Enter】
400
--> 確認してください。【Enter】
② 確認用 read 部分で入力を端末に指定する 【by @papiron さんより】
(入力リダイレクトで /dev/tty を指定)
# /dev/tty は、今使っている端末を示す
while read line; do
echo $line
read -p "--> 確認してください。【Enter】" stop < /dev/tty
done < /work/check.txt
/dev/tty(端末デバイス)
参考リンク:ttyとは?
参考リンク:ttyとかptsとかについて確認してみる
参考リンク:</dev/ttyについて
100
--> 確認してください。【Enter】
200
--> 確認してください。【Enter】
300
--> 確認してください。【Enter】
400
--> 確認してください。【Enter】
これでやりたかったことができる!!!
@papiron さん @angel_p_57 さん ご教授、ありがとうございました!!!