Com sedvocê pode fazer:
sed '24q;1,5d;12,18d' <infile >outfile
... Possivelmente uma solução mais eficiente poderia ser obtida head. Don já demonstrou como isso pode funcionar muito bem, mas eu também tenho brincado com isso. Algo que você pode fazer para lidar com este caso específico:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
... que chamaria headquatro vezes escrevendo para outfileou para, /dev/nulldependendo se o valor dessa iteração $né um número par ou ímpar.
Para casos mais gerais, juntei isso de outras coisas que já tinha:
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
Isso pode ser feito da seguinte maneira:
seq 100 | somehead -1 -5 6 -7 6
... que imprime ...
6
7
8
9
10
11
19
20
21
22
23
24
Ele espera que seu primeiro argumento seja uma contagem de repetição prefixada com a -ou, na sua falta, apenas a -. Se uma contagem for fornecida, ela repetirá o padrão de linha fornecido nos argumentos a seguir tantas vezes quanto especificado e parará assim que isso for feito.
Para cada argumento a seguir, ele interpretará um número inteiro negativo para indicar uma contagem de linhas que deve ser gravada /dev/nulle um número inteiro positivo para indicar uma contagem de linhas que deve ser gravada stdout.
Portanto, no exemplo acima, ele imprime as primeiras 5 linhas para /dev/null, as próximas 6 para stdout, as próximas 7 para /dev/nullnovamente e as próximas 6 novamente para stdout. Depois de atingir o último de seus argumentos e alternar completamente a -1contagem de repetições, ele sai. Se o primeiro argumento tivesse sido, -2ele repetiria o processo mais uma vez, ou -pelo maior tempo possível.
Para cada ciclo de arg, o whileloop é processado uma vez. No topo de cada loop, a primeira linha de stdiné lida na variável shell $l. Isso é necessário porque while head </dev/null; do :; donese repetirá indefinidamente - headindica em seu retorno quando ele atinge o final do arquivo. Portanto, a verificação no EOF é dedicada reade printfescreverá $lmais uma nova linha stdoutapenas se o segundo argumento for um número inteiro positivo.
A readverificação complica um pouco o loop, porque imediatamente após outro loop ser chamado - um forloop que itera sobre args, 2-$#conforme representado em $ncada iteração do whileloop pai . Isso significa que, para cada iteração, o primeiro argumento deve ser decrementado em um do valor especificado na linha de comando, mas todos os outros devem manter seus valores originais e, portanto, o valor do $_nmarcador var é subtraído de cada um, mas apenas mantém um valor valor maior que 0 para o primeiro argumento.
Isso constitui o loop principal da função, mas a maior parte do código está na parte superior e destina-se a permitir que a função armazene de maneira limpa até mesmo um pipe como entrada. Isso funciona chamando primeiro um background ddpara copiar seu arquivo tmpfile na saída em tamanhos de bloco de 4k por peça. A função então configura um loop de espera - que quase nunca deve completar nem um único ciclo completo - apenas para garantir que ddtenha feito pelo menos uma única gravação no arquivo antes que a função substitua seu stdin por um descritor de arquivo vinculado ao tmpfile e depois, desconecta imediatamente o arquivo comrm. Isso permite que a função processe o fluxo de maneira confiável, sem a necessidade de interrupções ou limpeza - assim que a função liberar sua reivindicação no arquivo fd, o tmpfile deixará de existir porque seu único link do sistema de arquivos nomeado já foi removido.
headetail? Nesse caso, sua solução é praticamente o melhor que você pode fazer. Se você tem permissão para usar outros programassedouawkpode oferecer soluções melhores (ou seja, com menos invocações de processos).