Когда работаешь с большими логами (гигабайты), вопрос «как читать быстрее и без лишнего расхода памяти?» становится критичным. Сегодня рассмотрим два подхода:
▪️ Подход 1: Чтение чанками (построчно или блочно). Классический цикл:
while IFS= read -r line; do
# обработка строки
done < big.log
➕ Память не забивается (читается построчно).
➖ Медленно при миллионах строк (много системных вызовов read).
Для ускорения можно читать чанками (например, по 1 МБ):
while chunk=$(dd bs=1M count=1 status=none); do
# обработка блока текста (можно разбить на строки)
echo "$chunk" | grep "ERROR"
done < big.log
➕ Гораздо меньше обращений к диску.
➕ Можно параллелить обработку чанков.
➖ Нужно дополнительно резать блоки на строки (grep, awk, cut).
▪️ Подход 2: mapfile / readarray. Современный и удобный способ загрузить файл в массив:
mapfile -t lines < big.log
echo "Первая строка: ${lines[0]}"
➕ Удобно: сразу доступ по индексам, можно обрабатывать батчами.
➕ Быстро для средних файлов (< 100–200 МБ).
➖ Огромные файлы (> 1 ГБ) забьют память.
Можно ограничить число строк:
mapfile -t -n 1000 lines < big.log # только первые 1000 строк
А для потоковой обработки чанками:
exec 3< big.log
while mapfile -t -n 1000 batch <&3 && ((${#batch[@]})); do
printf '%s\n' "${batch[@]}" | grep "ERROR"
done
exec 3<&-
➕ Работает как буферизация: читаем батчами по N строк.
➕ Ускоряет обработку за счёт снижения количества вызовов read.
В итоге получаем, что:
Для огромных логов (>1 ГБ) → читайте чанками (dd) или батчами (mapfile -n).
Для средних файлов → mapfile дает лучший баланс.
Для онлайн-потоков (tail -f) → старый добрый while read.
BashTex 📱 #bash