whileループ内でbashの入力を読み取る


97

私は次のようなbashスクリプトを持っています、

cat filename | while read line
do
    read input;
    echo $input;
done

しかし、これは明らかにI / Oリダイレクトの可能性があるため、whileループでファイル名から読み取ろうとするときのように、正しい出力を与えていません。

同じことをする他の方法は?


bashでユーザーを切り替え、スクリプトで切り替えられたユーザーの下で読み取りコマンドを実行すると、同じことが起こります
krupal

回答:



55

通常のstdinをユニット3にリダイレクトして、パイプライン内に取得し続けることができます。

{ cat notify-finished | while read line; do
    read -u 3 input
    echo "$input"
done; } 3<&0

ところで、実際にcatこの方法を使用している場合は、リダイレクトに置き換えれば、さらに簡単になります。

while read line; do
    read -u 3 input
    echo "$input"
done 3<&0 <notify-finished

または、そのバージョンでstdinとユニット3を交換できます。ユニット3でファイルを読み取り、stdinをそのままにしておきます。

while read line <&3; do
    # read & use stdin normally inside the loop
    read input
    echo "$input"
done 3<notify-finished

2番目のスクリプトがハングしているのはなぜですか?
Luca Borrione、2013

2
@LucaBorrione:どのように使っていますか?それが入力を与えるのを待っていますか?(それread lineは通知終了read -u 3 inputからの読み取りですが、書かれたようにそれを実行した場合はコンソールからの読み取りです)?
Gordon Davisson、2013

4

このようにループを変更してみてください:

for line in $(cat filename); do
    read input
    echo $input;
done

単体テスト:

for line in $(cat /etc/passwd); do
    read input
    echo $input;
    echo "[$line]"
done

@ w2lameもう一度テストして、「while」ループを「for」ループに変更します-私のために働いています。"sex -x"を試して、エラーの原因を確認してください
dimba

4
猫を使用しないでください。
ハイヴ

+1。これは、他の提案よりも特定のニーズに合わせて実装する方がはるかに簡単でした。
Nathan Wallace


3

2回読んだように見えますが、whileループ内の読み取りは必要ありません。また、catコマンドを呼び出す必要はありません。

while read input
do
    echo $input
done < filename

4
OPの目的は、ループ内の読み取りをユーザーから行うことですが、外側の読み取りはファイルから読み取ることです。したがって、彼らは2つの異なるソースからの2つの異なる読み取りを合法的に望んでいます。これは、質問のテキスト(内部readの動作を「正しくない[ファイル]から読み込もうとしているためfilename」と説明)と受け入れられた回答の両方から明らかです。
Charles Duffy

1

このパラメーター-uを読み取りで見つけました。

「-u 1」は「標準入力から読み取る」を意味します

while read -r newline; do
    ((i++))
    read -u 1 -p "Doing $i""th file, called $newline. Write your answer and press Enter!"
    echo "Processing $newline with $REPLY" # united input from two different read commands.
done <<< $(ls)

-6
echo "Enter the Programs you want to run:"
> ${PROGRAM_LIST}
while read PROGRAM_ENTRY
do
   if [ ! -s ${PROGRAM_ENTRY} ]
   then
      echo ${PROGRAM_ENTRY} >> ${PROGRAM_LIST}
   else
      break
   fi
done
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.