bash: добавление новой строки при перенаправлении файла - PullRequest
2 голосов
/ 18 января 2011

Вот как я читаю файл строка за строкой:

while read ROW
do
...
done < file

Я не использую другой синтаксис

cat file | while read ROW
do
...
done

потому что канал создает подоболочку и заставляет меня терять переменные окружения. Проблема возникает, если файл не заканчивается новой строкой: последняя строка не читается. Это легко решить в последнем синтаксисе, просто добавив новую строку:

(cat file; echo) | while read ROW
do
...
done

Как мне сделать то же самое в предыдущем синтаксисе, не открывая подоболочку или создавая временный файл (список довольно большой)?

Ответы [ 4 ]

2 голосов
/ 18 января 2011

Способ, который работает во всех оболочках, следующий:

#!/bin/sh

willexit=0
while [ $willexit == 0 ] ; do
read ROW || willexit=1
...
done < file

Прямое while read завершится, как только read встретит EOF, поэтому последняя строка не будет обработана. Проверяя возвращаемое значение за пределами while, мы можем обработать последнюю строку. Тем не менее, после чтения следует добавить дополнительный тест на пустоту $ ROW, так как в противном случае файл, последняя строка которого заканчивается новой строкой, сгенерирует ложное выполнение с пустой строкой, поэтому сделайте его

#!/bin/sh

willexit=0
while [ $willexit == 0 ] ; do
read ROW || willexit=1
if [ -n "$ROW"] ; then
  ...
fi
done < file
2 голосов
/ 18 января 2011
#!/bin/bash

while read ROW
 ...
done < <(cat file ; echo)
0 голосов
/ 04 августа 2011

Из ответа на аналогичный вопрос :

while IFS= read -r LINE || [ -n "${LINE}" ]; do
   ...
done <file

Часть IFS= не позволяет read удалить начальные и конечные пробелы (см. этот ответ ).

Если вам нужно по-разному реагировать в зависимости от того, есть ли у файла завершающий символ новой строки или нет (например, предупредить пользователя), вам придется внести некоторые изменения в условие while.

0 голосов
/ 18 января 2011

POSIX способ сделать это через именованный канал.

#!/bin/sh

[ -p mypipe ] || mkfifo mypipe

(cat num7; echo) > mypipe & 

while read line; do 
  echo "-->$line<--"
  export CNT=$((cnt+1))
done < mypipe

rm mypipe

echo "CNT is '$cnt'"

Input

$ cat infile
1
2
3
4
5$

выход

$ (cat infile;echo) > mypipe & while read line; do echo "-->$line<--"; export CNT=$((cnt+1)); done < mypipe; echo "CNT is '$cnt'"
[1] 22260
-->1<--
-->2<--
-->3<--
-->4<--
-->5<--
CNT is '5'
[1]+  Done                    ( cat num7; echo ) > mypipe
...