Обработка текстового файла построчно
Как Perl построчно читает файл, отбирает нужные строки по шаблону и превращает текстовый хаос в понятные данные.
Построчное чтение — способ обработки файла, при котором программа читает его не целиком, а по одной строке за раз, обрабатывает эту строку и переходит к следующей.
Зачем это нужно
Представь: на сервере лежит файл с логами — записями о том, кто и когда заходил на сайт. За месяц в нём миллионы строк. Тебе нужно найти только те, где были ошибки, и посчитать, сколько их было. Открывать файл в блокноте и листать глазами — не вариант, файл весит сотни мегабайт и просто не поместится на экране разумным образом.
Именно для таких задач и создавался Perl ещё в 1987 году. Его придумал системный администратор Ларри Уолл, которому надоело писать отчёты вручную. Он хотел язык, который умеет быстро прочитать текст, найти в нём закономерность и что-то с этим сделать. Спустя почти сорок лет Perl всё ещё остаётся одним из лучших инструментов именно для этой работы — обработки логов, конфигов, CSV-файлов и вообще любого текста.
Открываем файл и читаем построчно
Чтобы поработать с файлом, в Perl сначала нужно его открыть — связать имя файла на диске с переменной в программе, которую называют файловым дескриптором. Затем можно читать из него по одной строке.
open(my $fh, '<', 'server.log') or die "Не могу открыть файл: $!";
while (my $line = <$fh>) {
print $line;
}
close($fh);Вывод:
2026-06-30 09:12:01 INFO Пользователь user42 вошёл в систему
2026-06-30 09:12:15 ERROR Не удалось подключиться к базе данных
2026-06-30 09:13:02 INFO Пользователь user17 вышел из системы
...Разберём построчно, что здесь происходит:
open(my $fh, '<', 'server.log')— открывает файлserver.logна чтение. Знак'<'— это как раз указание «читать», а не «писать». Результат сохраняется в переменную$fh(от file handle, «файловый дескриптор»).or die "..."— если файл не открылся (например, его не существует), программа немедленно останавливается и печатает сообщение об ошибке.$!— специальная переменная Perl, в которой лежит текст последней системной ошибки.while (my $line = <$fh>)— сердце конструкции. Символы<$fh>означают «прочитать одну строку из дескриптора$fh». Каждый раз, когда циклwhileпроверяет условие, Perl читает следующую строку и кладёт её в$line. Когда строки заканчиваются,<$fh>возвращаетundef(пусто), и цикл завершается сам — не нужно отдельно проверять конец файла.close($fh)— закрывает файл, когда работа с ним закончена. Хорошая привычка, хоть Perl и закроет файл сам при завершении программы.
Отбираем строки по шаблону
Просто печатать файл целиком скучно — куда полезнее найти конкретные строки. Для этого Perl использует регулярные выражения — язык для описания текстовых шаблонов, встроенный прямо в синтаксис Perl (это одна из его суперспособностей). Оператор =~ проверяет, соответствует ли строка шаблону.
open(my $fh, '<', 'server.log') or die "Не могу открыть файл: $!";
my $error_count = 0;
while (my $line = <$fh>) {
if ($line =~ /ERROR/) {
print $line;
$error_count++;
}
}
close($fh);
print "Всего ошибок: $error_count\n";Вывод:
2026-06-30 09:12:15 ERROR Не удалось подключиться к базе данных
2026-06-30 09:47:33 ERROR Таймаут запроса к API
Всего ошибок: 2Здесь /ERROR/ — это и есть регулярное выражение, записанное между двумя слэшами. В простейшем виде это просто кусок текста, который Perl ищет внутри строки. Если слово ERROR где-то встретилось — условие истинно, строка печатается, а счётчик $error_count увеличивается на единицу оператором ++.
Вытаскиваем данные из строки
Найти строку — половина дела. Часто нужно достать из неё конкретный кусок: например, только время события. Для этого шаблон дополняют группами захвата — частями в круглых скобках, которые Perl запоминает отдельно.
open(my $fh, '<', 'server.log') or die "Не могу открыть файл: $!";
while (my $line = <$fh>) {
if ($line =~ /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) ERROR (.+)/) {
print "Время: $1, ошибка: $2\n";
}
}
close($fh);Вывод:
Время: 2026-06-30 09:12:15, ошибка: Не удалось подключиться к базе данных
Время: 2026-06-30 09:47:33, ошибка: Таймаут запроса к APIШаблон выглядит пугающе, но по частям всё понятно:
^— «строка должна начинаться с этого места» (иначеERRORмогло бы найтись где угодно посреди строки).\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}—\dозначает «любая цифра», а{4}— «ровно четыре раза». То есть это описание даты и времени вида2026-06-30 09:12:15.- Круглые скобки
( ... )вокруг даты — первая группа захвата. То, что она «поймает», попадёт в специальную переменную$1. (.+)— вторая группа захвата. Точка.значит «любой символ», плюс+— «один или больше раз». То есть «захватить весь оставшийся текст». Он попадёт в переменную$2.
После успешного совпадения Perl автоматически заполняет переменные $1, $2 и так далее — по числу групп в шаблоне, слева направо. Это очень удобно: не нужно вручную вырезать подстроки, достаточно один раз описать форму данных.
Частые ошибки
- Забыть проверить, открылся ли файл. Без
or dieпрограмма при отсутствующем файле просто тихо ничего не сделает, и разобраться, что пошло не так, будет сложнее. - Перепутать
=~с обычным присваиванием=.=~— это «проверить строку на соответствие шаблону», а не «присвоить значение». Одна лишняя тильда — и программа не скомпилируется. - Забыть про перенос строки в конце. Каждая строка, прочитанная через
<$fh>, обычно содержит символ конца строки\nна конце. Если вывести такую строку без изменений вперемешку с другим текстом, можно получить лишние переносы. Убрать его помогает функцияchomp. - Слишком жадный шаблон. Символ
.+захватывает как можно больше символов, и иногда «проглатывает» не то, что задумывалось. В сложных случаях стоит делать шаблон точнее, а не полагаться на то, что «плюс возьмёт всё нужное».
Итоги
- Файл открывают через
open(my $fh, '<', 'имя_файла')и читают по одной строке цикломwhile (my $line = <$fh>). - Оператор
=~проверяет строку на соответствие регулярному выражению — шаблону, который описывает, какой текст мы ищем. - Круглые скобки в шаблоне создают группы захвата, значения которых после совпадения оказываются в переменных
$1,$2и так далее. - Такой способ обработки — основа огромного числа реальных задач: анализ логов, поиск ошибок, сбор статистики из текстовых файлов.