Con sed
te 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 head
4 volte scrivendo su outfile
o su a /dev/null
seconda che il valore di quella iterazione $n
sia 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/null
e 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/null
e le successive 6 su stdout
. Dopo aver raggiunto l'ultimo dei suoi argomenti e completamente -1
ripetuto 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 while
ciclo viene elaborato una volta. Nella parte superiore di ogni ciclo stdin
viene letta la prima riga da nella variabile shell $l
. Questo è necessario perché while head </dev/null; do :; done
si ripeterà indefinitamente - head
indica al suo ritorno quando ha raggiunto la fine del file. Quindi il controllo contro EOF è dedicato read
e printf
scriverà $l
più una nuova riga stdout
solo se il secondo argomento è un numero intero positivo.
Il read
controllo complica un po 'il ciclo perché immediatamente dopo viene chiamato un altro ciclo - un for
ciclo che scorre su args 2-$#
come rappresentato $n
per ogni iterazione del suo while
ciclo 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 $_n
marcatore 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 dd
per 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 dd
abbia 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.
head
etail
? In tal caso, la tua soluzione è praticamente la migliore che puoi fare. Se hai il permesso di usare altri programmised
oawk
potresti consentire soluzioni migliori (ad es. Con meno invocazioni di processo).