Анализ файла, разделенного запятыми, в скрипте bash с циклом while

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

bob,mechanic,single,swimming,/bob/tmp,batman,
joe,architect,married,tennis,/joe/tmp,superman,34

С помощью этого скрипта:

#!/bin/bash

#|| [[ -n "$input" ]]

while IFS=, read -r a b c d e f g; do
    echo "$a"

done < "commafile.txt"

Но когда я запускаю сценарий (называемый parsecommas) с./parsecommas из командной строки, сценарий немедленно завершается без вывода.

Что я делаю неправильно? Я использую OSX Yosemite и использую xcode для редактирования скрипта, а затем терминал для его запуска. Я проверил на наличие неисправных невидимых, но не нашел ни одного. commafile.txt находится в той же директории, что и parsecommas bash-скрипта.

РЕДАКТИРОВАТЬ: После запуска программы на С ++ и возможности прочитать только последнюю строку файла, я понял, что эта проблема может быть связана не с моим кодом, а с методом, который я использовал для создания текстовых файлов. я использовал

touch commafile.txt

чтобы создать мой файл, и я смог прочитать только последнюю строку файла при использовании getline (file, line) в программе на C++. Кто-нибудь еще сталкивался с этой проблемой раньше? Что может быть не так с моим Mac/Text Editor?

cat commafile.txt

Печатает только последнюю строку в файле, в то время как при открытии файла в XCode или TextEditor отображаются все строки. Я скопировал и вставил содержимое слова doc в поле в форме поля в commafile.txt.

1 ответ

Решение

Если cat filename печатает только последнюю строку, это означает, что ваш файл почти наверняка использует CR (возврат каретки, \r), а не LFs (\n) или CRLF (\r\n) новые строки. Вы можете воспроизвести эту ошибку, создав файл следующим образом: printf '%s\r' "bob,mechanic,single,swimming,/bob/tmp,batman," "joe,architect,married,tennis,/joe/tmp,superman,34" >commafile.txt

Это приводит к cat показывает только последнюю строку файла, потому что \r Символ заставляет курсор возвращаться к началу той же строки при переходе между записями. Это объясняет вашу ошибку, потому что read Встроенная оболочка ожидает допустимую строку UNIX, которая заканчивается \n; если ваш код не содержит \nс, тогда read вернет ложное значение и цикл не запустится.

Вы можете исправить это следующим образом:

# replace \r characters with \n
tr '\r' '\n' <commafile.txt >commafile.fixed && mv commafile{.fixed,.txt}

Кроме того, вы можете изменить цикл, чтобы он ожидал этот формат вместо стандартного текстового файла UNIX, передав -d $'\r' в read:

while IFS=, read -r -d $'\r' a rest; do
  printf '%s\n' "$a" # less buggy than echo
done
Другие вопросы по тегам