Angenommen, ich habe eine riesige Textdatei (>2 GB) und möchte nur cat
die Zeilen X
zu Y
(z. B. 57890000 bis 57890010).
Soweit ich weiß, kann ich dies tun, indem ich head
pfeife in tail
oder umgekehrt, also
head -A /path/to/file | tail -B
oder alternativ
tail -C /path/to/file | head -D
wobei A
,B
,C
und D
kann aus der Anzahl der Zeilen in der Datei berechnet werden, X
und Y
.
Aber es gibt zwei Probleme mit diesem Ansatz:
- Sie müssen
A
berechnen ,B
,C
undD
. - Die Befehle könnten
pipe
miteinander viele mehr Zeilen, die ich nicht lesen möchte (z. B. wenn ich nur ein paar Zeilen inmitten einer riesigen Datei lese)
Gibt es eine Möglichkeit, die Shell einfach mit den gewünschten Zeilen arbeiten und ausgeben zu lassen? (wobei nur X
angegeben wird und Y
)?
Akzeptierte Antwort:
Ich schlage den sed
vor Lösung, aber der Vollständigkeit halber,
awk 'NR >= 57890000 && NR <= 57890010' /path/to/file
Nach der letzten Zeile ausschneiden:
awk 'NR < 57890000 { next } { print } NR == 57890010 { exit }' /path/to/file
Geschwindigkeitstest (hier auf macOS, YMMV auf anderen Systemen):
- Datei mit 100.000.000 Zeilen, generiert von
seq 100000000 > test.in
- Lesezeilen 50.000.000–50.000.010
- Tests in keiner bestimmten Reihenfolge
real
Zeit wie vonbash
gemeldet eingebautetime
4.373 4.418 4.395 tail -n+50000000 test.in | head -n10
5.210 5.179 6.181 sed -n '50000000,50000010p;57890010q' test.in
5.525 5.475 5.488 head -n50000010 test.in | tail -n10
8.497 8.352 8.438 sed -n '50000000,50000010p' test.in
22.826 23.154 23.195 tail -n50000001 test.in | head -n10
25.694 25.908 27.638 ed -s test.in <<<"50000000,50000010p"
31.348 28.140 30.574 awk 'NR<57890000{next}1;NR==57890010{exit}' test.in
51.359 50.919 51.127 awk 'NR >= 57890000 && NR <= 57890010' test.in
Dies sind keineswegs präzise Benchmarks, aber der Unterschied ist deutlich und wiederholbar genug*, um einen guten Eindruck von der relativen Geschwindigkeit jedes dieser Befehle zu vermitteln.
*:Außer zwischen den ersten beiden, sed -n p;q
und head|tail
, die im Wesentlichen gleich zu sein scheinen.