Bash цикл, который читает файл строка за строкой - PullRequest
10 голосов
/ 20 декабря 2011

Есть два способа построчного чтения файла, которые я хочу обсудить здесь:

#!/bin/bash    

while read line    
do    
    echo-e "$ line \ n"    
done <file.txt

и

#!/bin/bash    
exec 3<file.txt

while read line    
do    
    echo-e "$ line \ n"    
done

Итак, первая версия работает нормально, но я не понимаю механизм работы цикла с файлом. Но механизм второй версии я понимаю. Но тут я не понимаю, почему он зависает и ничего не печатает.

Ответы [ 4 ]

9 голосов
/ 20 декабря 2011

Первый цикл работает, потому что перенаправление после done применяется ко всему циклу, поэтому read выполняет чтение из файла, а не из стандартного ввода сценария.

Второйверсия зависает, потому что read читает из дескриптора файла 0, который является стандартным вводом, и вы ничего там не набрали.Строка exec перенаправляет файловый дескриптор 3 для чтения из файла, но вы не читаете из файлового дескриптора 3.

Вы можете спасти вторую, используя:

exec <file.txt

Сейчасстандартный ввод читается из именованного файла.

4 голосов
/ 20 декабря 2011

Это может работать для вас:

exec 3<file.txt

while read -u3 line
do
    echo -e "$line \n"
done

-u3 читает из файлового дескриптора 3

Странно, что echo не имеет переключателя дополнения, как у команды ksh print.

3 голосов
/ 20 декабря 2011

В ваших скриптах есть несколько ошибок.

  1. Пробел между $ и именем переменной. (может быть плохо редактировать)
  2. Пробел между echo и -e. (может быть плохо редактировать)
  3. Упоминание о прочтении в дескрипторе файла, где файл открыт. Вы читаете файл по дескриптору 0, а exec работает по дескриптору 3.

Это должно быть примерно так -

#!/bin/bash    
exec 3<file.txt

while read line  
do
    echo -e "$line \n"
done <&3
0 голосов
/ 14 апреля 2014

-u3 отлично подходит для моей цели (чтение только следующей строки)

#!/bin/bash

logs=(*Logs.txt)
[[ -e "${logs[0]}" ]] || exit 0

exec 3<"${logs[0]}"

while read -u3 line
do
        if [[ $(echo "$line"| grep -c SCSI_STATUS_CHECK_CONDITION) -eq 1 ]]; then
                read -u3 line
                echo "$line"
        fi
done
...