Чтение ввода в bash внутри цикла while

У меня есть скрипт bash, который выглядит примерно так:

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

но это явно не дает мне правильного вывода, так как когда я читаю в цикле while, он пытается прочитать имя файла из-за возможного перенаправления ввода-вывода.

Любой другой способ сделать то же самое?

5 ответов

Решение

Читайте с управляющего оконечного устройства:

read input </dev/tty

больше информации: http://compgroups.net/comp.unix.shell/Fixing-stdin-inside-a-redirected-loop

Вы можете перенаправить обычный 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

Попробуйте изменить цикл следующим образом:

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

Похоже, вы читаете дважды, чтение внутри цикла while не требуется. Также вам не нужно вызывать команду cat:

while read input
do
    echo $input
done < filename

Я нашел этот параметр -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)
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
Другие вопросы по тегам