Идея для этой статьи у меня появилась, когда я увидел в одном из блогов, что данную задачу предлагается решать следующим однострочным кодом на языке Perl:
echo -e '1\n2\n3' | perl -nalE 'push(@lines, $_); }{ say $lines[$_] foreach 0..$#lines -1'А как же утилита head спросите Вы меня? Да, это лучший вариант. Но как оказалось, в некоторых системах нельзя использовать эту утилиту с отрицательным значением для параметра n (в случае когда неизвестно сколько строк в файле). О чем в исходной статье и было сказано, перед тем как предложить такой вариант решения.
Но, как мне кажется, в этом фрагменте кода есть две проблемы:
echo -e '1\n2\n3' | perl -nale 'push(@l, $_); print shift(@l) if @l> 1;'Код совсем простой, но давайте его рассмотрим подробнее. Во-первых, мы не храним весь файл в памяти, а только то количество строк, которое мы не хотим выводить - своего рода буфер. Во-вторых, мы сразу принимаем решение о том выводить нам строку или нет. Количество строк, которое мы не выводим с конца задается числом. В данном примере это одна строка.
Замеры на потребляемую память я тестировал на файле размером 72M
ls -lah big.file -rw-r--r-- 1 madskill madskill 72M ноя 1 03:56 big.fileДля первого варианта, получил следующие значения
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 23400 madskill 20 0 205844 188952 3960 S 0,0 4,8 0:07.44 perlА для моего варианта следующие
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 23413 madskill 20 0 21056 3492 3248 S 0,0 0,1 0:10.71 perlИз приведенных выше замеров видно, что мой вариант более экономично использует память. Но на этом я не остановился и далее грубо сравнил оба варинта по производительности. Получилось, что разницы почти нет. При повторных запусках был быстрее то один, то другой вариант. А разница между ними была очень маленькой.
time cat big.file | perl -nalE 'push(@lines, $_); }{ say $lines[$_] foreach 0..$#lines -1;'> /dev/null real 0m1,789s user 0m1,662s sys 0m0,188s time cat big.file | perl -nale 'push(@l, $_); print shift(@l) if @l> 1;'> /dev/null real 0m1,732s user 0m1,688s sys 0m0,116s