Mit sed
könnten Sie tun:
sed '24q;1,5d;12,18d' <infile >outfile
... Möglicherweise könnte eine effizientere Lösung mit gehabt werden head
. Don hat bereits gezeigt, wie das sehr gut funktionieren könnte, aber ich habe auch damit herumgespielt. Etwas, das Sie tun könnten, um diesen speziellen Fall zu behandeln:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
... die head
viermal aufschreiben würde outfile
, /dev/null
je nachdem, ob der Wert dieser Iteration $n
eine gerade oder eine ungerade Zahl ist.
Für allgemeinere Fälle habe ich dies aus einigen anderen Sachen zusammengeschustert, die ich bereits hatte:
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
Dies kann dein Ding machen wie:
seq 100 | somehead -1 -5 6 -7 6
... was druckt ...
6
7
8
9
10
11
19
20
21
22
23
24
Es erwartet, dass sein erstes Argument eine Wiederholungszahl ist -
, der ein oder nur ein a vorangestellt ist -
. Wenn eine Zählung angegeben wird, wird das in den folgenden Argumenten angegebene Linienmuster so oft wie angegeben wiederholt und angehalten, sobald dies geschehen ist.
Für jedes folgende Argument wird eine negative Ganzzahl interpretiert, um eine Zeilenanzahl anzugeben, in die geschrieben werden soll, /dev/null
und eine positive Ganzzahl, um eine Zeilenanzahl anzugeben, in die geschrieben werden soll stdout
.
Im obigen Beispiel werden also die ersten 5 Zeilen an /dev/null
, die nächsten 6 an stdout
, die nächsten 7 an /dev/null
und die nächsten 6 erneut an gedruckt stdout
. Nachdem es das letzte seiner Argumente erreicht und die -1
Wiederholungszählung vollständig durchlaufen hat , wird es beendet. Wenn das erste Argument gewesen wäre -2
, hätte es den Vorgang noch einmal wiederholt, oder wenn es -
so lange wie möglich gewesen wäre.
Für jeden Arg-Zyklus wird die while
Schleife einmal durchlaufen. Am Anfang jeder Schleife wird die erste Zeile von stdin
in die Shell-Variable eingelesen $l
. Dies ist notwendig, da while head </dev/null; do :; done
es auf unbestimmte Zeit wiederholt wird - head
zeigt in seiner Rückgabe an, wann das Dateiende erreicht ist. Die Prüfung gegen EOF ist also nur dann gewidmet read
und printf
wird $l
plus eine neue Zeile geschrieben, stdout
wenn das zweite Argument eine positive ganze Zahl ist.
Die read
Prüfung verkompliziert die Schleife ein wenig, da unmittelbar nach dem Aufruf einer anderen Schleife eine for
Schleife über Argumente iteriert, 2-$#
wie in $n
für jede Iteration ihrer übergeordneten while
Schleife dargestellt. Dies bedeutet, dass für jede Iteration das erste Argument von dem in der Befehlszeile angegebenen Wert um eins dekrementiert werden muss, alle anderen jedoch ihre ursprünglichen Werte beibehalten sollten. Daher wird der Wert des $_n
Markers var von jedem subtrahiert, enthält jedoch immer nur a Wert größer als 0 für das erste Argument.
Dies stellt die Hauptschleife der Funktion dar, aber der Großteil des Codes befindet sich oben und soll es der Funktion ermöglichen, selbst eine Pipe als Eingabe sauber zu puffern. Dies funktioniert, indem zuerst ein Hintergrundbild dd
aufgerufen wird, um es bei der Ausgabe in Blockgrößen von 4 KB pro Stück in ein tmpfile zu kopieren. Die Funktion richtet dann eine Halteschleife ein, die fast nie einen einzigen vollständigen Zyklus abschließen sollte, um sicherzustellen, dass dd
mindestens ein einziger Schreibvorgang in die Datei ausgeführt wurde, bevor die Funktion ihren Standard durch einen Dateideskriptor ersetzt, der mit tmpfile und verknüpft ist Danach wird die Verknüpfung der Datei sofort mit aufgehobenrm
. Auf diese Weise kann die Funktion den Stream zuverlässig verarbeiten, ohne dass Traps erforderlich sind oder anderweitig bereinigt werden müssen. Sobald die Funktion den Anspruch auf dem fd freigibt, ist die tmpfile nicht mehr vorhanden, da der einzige benannte Dateisystemlink bereits entfernt wurde.
head
undtail
? Wenn ja, ist Ihre Lösung so ziemlich das Beste, was Sie tun können. Wenn Sie andere Programme verwenden dürfensed
oderawk
möglicherweise bessere Lösungen zulassen (dh mit weniger Prozessaufrufen).