Чтение файлов в bash
Есть три основных идиоматических способка чтения файлов в bash. Некоторые из них загружают файл в память целиков, другие читают его построчно.
read
Возможные траблы
Пробую получить данные из /etc/password.
Команда выше не выведет данные в bash (в zsh работает), ибо данные попадут в подоболочку, созданную пайпом (|), и не выйдут оттуда. Поэтому есть другой рабочий вариант для такого случая:
Но все еще нет остальных данных. Проблема в том, что
-d
- это разделительпо концу строки, а не по полям ($IFS
). Поэтому вот конечное решение:
lastpipe
В bash 4.0+ можно установить параметр
shopt -s lastpipe
, чтобы последняя команда конвейера выполнялась в текущей оболочке и скрипт мог видеть окружение.
Этот прием работает, только если отключено управление заданиями (в скриптах оно отключено по умолчанию, но может быть включено в интерактивном сеансе).
Отключить управление заданиями можно с помощью командыset +m
, но при этом выключится реакция на комбинации клавиш CTRL-C и CTRL-Z, а также командыfg
иbg
, поэтому НЕ рекомендую ее юзать.
Простое построчное чтение файла
mapfile
Команда
mapfile
илиreadarray
читает файл в массив (список).
Появилась в bash 4.0.
Самые часто используемые параметры:
-n count
— ограничивает кол-во читаемых строк-s count
— пропускает указанное кол-во строк-c/-C
— отображение индикатора хода выполнения операции
Чтение файла, загружая его в память
В самом простом случае mapfile
грузит весь файл в память:
Чтение файла порциями
Ключ -n
усложняет работу тем, что нужно будет проверять, были ли прочитаны какие-то данные (значение ${nodes[@]}
отлично от нуля), иначе while mapfile
будет выполняется вечно.
Чтение файла методом “грубой силы”
Изменение $IFS
при чтении файлы
IFS - Internal Field Separator (внутренний разделитель полей).
Переменная$IFS
применима, когда требуется разбить строку на слова.
По умолчанию, используетсяIFS=$' \t\n'
(<пробел><табуляция><перевод строки>) с механизмом экранирования$''
по стандарту ANSI C.
Если уверен, что нужно изменить $IFS
, сделай это в функции (как локальное переменное) или локально по отношению к команде (IFS=':' read ...
) (Локальные переменные).
Имитации файлов (pretend files) или подстановка процессов
Если нужно обработать только часть файлы, можно юзать временные файлы (хоть это и гемор):
Пример без использования имитации файлов:
С использованием имитации файлов:
Так-то этот прием называется подстановка процессов.
Соус: Книга “Идиомы Bash” → Глава 9. “Файлы и не только”