Con sedte potresti fare:
sed '24q;1,5d;12,18d' <infile >outfile
... Forse si potrebbe avere una soluzione più efficiente con head. Don ha già dimostrato come potrebbe funzionare molto bene, ma ci ho anche provato. Qualcosa che potresti fare per gestire questo caso specifico:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
... che chiamerebbe head4 volte scrivendo su outfileo su a /dev/nullseconda che il valore di quella iterazione $nsia un numero pari o dispari.
Per casi più generali, l'ho messo insieme da alcune altre cose che avevo già:
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
Questo può fare le tue cose come:
seq 100 | somehead -1 -5 6 -7 6
... che stampa ...
6
7
8
9
10
11
19
20
21
22
23
24
Si aspetta che il suo primo argomento sia un conteggio delle ripetizioni con il prefisso a -, o, in mancanza, solo a -. Se viene fornito un conteggio, questo ripeterà il modello di linea indicato nei seguenti argomenti quante volte specificato e si interromperà non appena lo avrà fatto.
Per ogni arg che segue interpreterà un numero intero negativo per indicare un conteggio di righe su cui scrivere /dev/nulle un numero intero positivo per indicare un conteggio di righe su cui scrivere stdout.
Quindi nell'esempio sopra stampa le prime 5 righe su /dev/null, le successive 6 su stdout, le successive 7 su /dev/nulle le successive 6 su stdout. Dopo aver raggiunto l'ultimo dei suoi argomenti e completamente -1ripetuto attraverso il conteggio delle ripetizioni, si chiude. Se il primo argomento fosse stato -2, avrebbe ripetuto il processo ancora una volta, o se fosse stato il più -a lungo possibile.
Per ogni ciclo arg il whileciclo viene elaborato una volta. Nella parte superiore di ogni ciclo stdinviene letta la prima riga da nella variabile shell $l. Questo è necessario perché while head </dev/null; do :; donesi ripeterà indefinitamente - headindica al suo ritorno quando ha raggiunto la fine del file. Quindi il controllo contro EOF è dedicato reade printfscriverà $lpiù una nuova riga stdoutsolo se il secondo argomento è un numero intero positivo.
Il readcontrollo complica un po 'il ciclo perché immediatamente dopo viene chiamato un altro ciclo - un forciclo che scorre su args 2-$#come rappresentato $nper ogni iterazione del suo whileciclo genitore . Ciò significa che per ogni iterazione il primo arg deve essere decrementato di uno dal valore specificato nella riga di comando, ma tutti gli altri devono conservare i loro valori originali, e quindi il valore del $_nmarcatore var viene sottratto da ciascuno, ma contiene sempre e solo un valore maggiore di 0 per il primo arg.
Ciò costituisce il ciclo principale della funzione, ma la maggior parte del codice è nella parte superiore e ha lo scopo di consentire alla funzione di bufferizzare in modo pulito anche un tubo come input. Funziona chiamando prima uno sfondo ddper copiarlo in un file tmp in uscita a blocchi di 4k un pezzo. La funzione quindi imposta un ciclo di attesa - che non dovrebbe quasi mai completare nemmeno un singolo ciclo completo - solo per garantire che ddabbia effettuato almeno una singola scrittura nel file prima che la funzione sostituisca il suo stdin con un descrittore di file collegato al file tmp e successivamente scollega immediatamente il file conrm. Ciò consente alla funzione di elaborare in modo affidabile il flusso senza richiedere trap o altrimenti per la pulizia - non appena la funzione rilascia la richiesta sul file fd il file tmp cesserà di esistere perché il suo unico collegamento al filesystem denominato è già stato rimosso.
headetail? In tal caso, la tua soluzione è praticamente la migliore che puoi fare. Se hai il permesso di usare altri programmisedoawkpotresti consentire soluzioni migliori (ad es. Con meno invocazioni di processo).