Сценарий оболочки не читает последнюю строку из sysin

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

line1
line2
line3

Мой код:

#!/bin/bash
while read line
do
  echo "$line"
done

И вывод:

$ ./test.sh < data.txt
line1
line2

Если я записываю в конце моего файла, вывод пустой строки будет правильным. Но мне это не нравится. Как это исправить?

3 ответа

Решение

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

#!/bin/bash
while true; do
  line=''
  read line
  if [ -z "$line" ]; then
    break
  fi
  echo "$line"
done

Идиома для этого:

while read -r line || [[ $line ]]; do
  : process "$line"
done

Таким образом, мы продолжаем цикл пока либо:

  • Мы читаем правильную строку текста (которая требует новой строки)
  • У нас было частичное чтение (что приводит к ненулевому состоянию выхода, но оставляет переменную непустой).

Могу поспорить, что в data.txt отсутствует завершающий символ новой строки, попробуйте проверить с помощью

od -xa data.txt

Посмотрите на конец:

$ od -xa data.txt
0000000    696c    656e    0a31    696c    656e    0a32    696c    656e
          l   i   n   e   1  nl   l   i   n   e   2  nl   l   i   n   e
0000020    0033
          3
0000021

Если вы видите выше, вам не хватает новой строки.

$ od -xa data-with-nl.txt
0000000    696c    656e    0a31    696c    656e    0a32    696c    656e
          l   i   n   e   1  nl   l   i   n   e   2  nl   l   i   n   e
0000020    0a33
          3  nl
0000022

Некоторые снаряды также покажут % подпишите, если завершающий символ новой строки отсутствует, попробуйте:

$ cat data.txt
line1
line2
line3%
$
Другие вопросы по тегам