С sedвами можно сделать:
sed '24q;1,5d;12,18d' <infile >outfile
... Возможно, более эффективное решение может быть найдено с head. Дон уже продемонстрировал, как это может работать очень хорошо, но я тоже с этим поиграл. Что-то, что вы могли бы сделать, чтобы справиться с этим конкретным случаем:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
... который будет вызывать head4 раза, записывая либо в, outfileлибо в /dev/nullзависимости от того, является ли значение этой итерации $nчетным или нечетным числом.
Для более общих случаев я собрал это вместе с некоторыми другими вещами, которые у меня уже были:
somehead()(
### call it like:
### somehead -[repeat] [-][numlines]* <infile >outfile
set -e -- "${1#-}" "$@" #-e for arg validation
r=; cd -- "${TMP:-/tmp}" #go to tmp
dd bs=4096 of="$$$$" <&4 2>&3 & #dd <in >tmpfile &bg
until [ -s "$$$$" ]; do :; done #wait while tmpfile empty
exec <"$$$$" 4<&-; rm "$$$$" #<tmpfile; rm tmpfile
[ "$3${1}0" -ne "$3${2#?}0" ] || #validate args - chk $1
shift "$(((r=-${1:--1})||1))"; shift #shift 1||2
while [ "$(((r+=(_n=1))-1))" -ne 0 ] && #while ! $rptmax &&
IFS= read -r l && # ! EOF &&
printf "%.$(($1>0?${#l}+1:0))s" "$l # ? printf do
"; do for n do [ "${n#-}" -gt 0 ] || exit #args all -[nums>0]
head "-n$((${n#-}-_n))" >&"$((n>(_n=0)?1:3))" #head -n?$1 >?[+-]
done; done #done and done
) 4<&0 3>/dev/null #4<for dd 3>for head
Это может сделать вашу вещь, как:
seq 100 | somehead -1 -5 6 -7 6
... который печатает ...
6
7
8
9
10
11
19
20
21
22
23
24
Он ожидает, что его первым аргументом будет число повторений с префиксом -или, в случае неудачи, просто a -. Если указан счетчик, он будет повторять шаблон линии, заданный в следующих аргументах, столько раз, сколько указано, и останавливается, как только это будет сделано.
Для каждого следующего аргумента он будет интерпретировать отрицательное целое число, чтобы указать количество строк, в которое следует записать, /dev/nullи положительное целое число, чтобы указать количество строк, в которое следует записать stdout.
Таким образом, в приведенном выше примере он печатает первые 5 строк до /dev/null, следующие 6 до stdout, следующие 7 до /dev/nullснова и следующие 6 еще раз до stdout. Достигнув последнего из его аргументов и полностью циклически -1повторяя счетчик, он затем выходит. Если бы это был первый аргумент, -2он бы повторил процесс еще раз или, если -мог, так долго, как мог.
Для каждого цикла arg цикл whileобрабатывается один раз. В верхней части каждого цикла первая строка из stdinчитается в переменную оболочки $l. Это необходимо, потому что while head </dev/null; do :; doneбудет повторяться до бесконечности - headуказывает в своем возвращении, когда он достиг конца файла. Таким образом, проверка на EOF посвящена readи printfзапишет $lплюс новую строку, stdoutтолько если второй аргумент является положительным целым числом.
readПроверка усложняет петлю немного , потому что сразу же после того, как другой цикл называется - forцикл , который перебирает арг , 2-$#как представлено в $nкаждой итерации родительского whileцикла. Это означает, что для каждой итерации первый аргумент должен быть уменьшен на единицу от значения, указанного в командной строке, но все остальные должны сохранять свои исходные значения, и поэтому значение $_nмаркера var вычитается из каждого, но только когда-либо содержит значение больше 0 для первого аргумента
Это составляет основной цикл функции, но основная часть кода находится вверху и предназначена для того, чтобы функция могла чисто буферизовать даже канал в качестве входных данных. Это работает, сначала вызывая фон ddдля копирования его в tmpfile на выходе с размерами блоков 4k за штуку. Затем функция устанавливает цикл удержания - который почти никогда не должен завершать даже один полный цикл - просто для того, чтобы гарантировать, что ddбыла произведена хотя бы одна запись в файл, прежде чем функция затем заменит свой стандартный ввод дескриптором файла, связанным с tmpfile, и после этого сразу же отменяет связь файла сrm, Это позволяет функции надежно обрабатывать поток, не требуя перехватов или других действий для очистки - как только функция освобождает свою заявку на fd, tmpfile перестанет существовать, поскольку ее единственная именованная ссылка файловой системы уже удалена.
headиtail? Если это так, то ваше решение - самое лучшее, что вы можете сделать. Если вам разрешено использовать другие программыsedили выawkможете использовать более приятные решения (например, с меньшим количеством вызовов процессов).