Ich suche nach der einfachsten Methode, um die längste Zeile in einer Datei zu drucken. Ich googelte und schien überraschenderweise keine Antwort zu finden. Ich drucke häufig die Länge der längsten Zeile in einer Datei, aber ich weiß nicht, wie ich die längste Zeile drucken soll. Kann jemand eine Lösung zum Drucken der längsten Zeile in einer Datei bereitstellen? Danke im Voraus.
35
Antworten:
UPD : Zusammenfassung aller Hinweise in den Kommentaren
quelle
cat
) und das Verwenden einer Pipe sind kostspielige Vorgänge, ganz zu schweigen davon, dass awk die Datei effizienter nur lesen kann. Die Auswirkungen auf die Leistung sind definitiv spürbar, wenn dies häufig gemacht wird, und trotzdem sind Sie völlig missbräuchlichcat
.cat
ist hier nicht nutzlos. Es mag für einen Computer unbrauchbar sein, aber für einen menschlichen Leser könnte es einen Wert liefern. Die erste Variante zeigt deutlich die Eingabe. Der Fluss ist natürlicher (von links nach rechts). Im zweiten Fall wissen Sie nicht, was die Eingabe ist, es sei denn, Sie scrollen durch das Fenster.cat
.< file command
funktioniert gut< filename command
ist gleichbedeutend mitfilename < command
in jeder Shell die ich ausprobiert habe. Aber sobald Sie sich dessen bewusst sind, können Sie es nutzen, wenn Sie lange Pipes schreiben, die klar die Richtung des Datenflusses anzeigen (ohne einen zusätzlichen Befehl aufzurufen):< input-file command1 | command2 | command3 > output-file
quelle
Dies liest zuerst die Datei innerhalb der Befehlsersetzung und gibt die Länge der längsten Zeile aus (
expand
konvertiert zuvor Tabulatoren in Leerzeichen, um die Semantik von zu überwindenwc -L
- jede Registerkarte in der Zeile addiert 8 anstelle von 1 zur Zeilenlänge). Diese Länge wird dann in einemsed
Ausdruck verwendet, der "Finde eine Zeile mit dieser Anzahl von Zeichen, drucke sie aus und beende sie dann" bedeutet. Das kann also tatsächlich so optimal sein, wie die längste Zeile sich in der Nähe des oberen Endes der Datei befindet, heheh (danke für die tollen und konstruktiven Kommentare).Ein anderer, ich hatte früher gedacht als der sed (in bash):
quelle
-L, --max-line-length
die Länge der längsten Zeile gemäß der Manpage aus. Wenn Sie jedoch tiefer graben (z. B. wenn Sie falsche / unerwartete Ergebnisse erhalten), erhöht diese Option die Länge für jedes Zeichen mit 1 Tab um 8 finden Sie in diesem Unix & Linux Q / A\x09
sed -rn "/.{$(<file expand -t1 |wc -L)}/p" file
read line
wird Backslash-escaped Zeichen als wörtliche Zeichen, zB interpretieren\A
resloves zuA
, was natürlich effektiv einen kürzeren als die tatsächlichen Byte-Nutzungsberichte ... dies zu verhindern entkommen Interpretation, zu verwenden:read -r line
. . . . Um die sed + wc- Version nach der ersten "längsten Zeile" zu beenden, wechseln Siep
zu{p;q}
..sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file
Hier ist eine Perl-Lösung:
Oder möchten , wenn Sie drucken alle die längste Zeile
Da ich nichts Besseres zu tun hatte, führte ich einige Benchmarks für eine 625M-Textdatei durch. Überraschenderweise war meine Perl-Lösung durchweg schneller als die anderen. Zugegeben, der Unterschied zur akzeptierten
awk
Lösung ist winzig, aber es ist da. Offensichtlich sind Lösungen, die mehrere Zeilen drucken, langsamer, sodass ich nach Typ sortiert habe, am schnellsten bis am langsamsten.Nur eine der längsten Zeilen drucken:
Alle längsten Zeilen drucken:
quelle
Grep die erste längste Zeile
Der Befehl ist ohne Übung ungewöhnlich schwer zu lesen, da er Shell- und Regexp-Syntax mischt.
Zur Erklärung verwende ich zunächst den vereinfachten Pseudocode. Die mit beginnenden Zeilen
##
verlaufen nicht in der Shell.Dieser vereinfachte Code verwendet den Dateinamen F und lässt aus Gründen der Lesbarkeit Anführungszeichen und Teile von regulären Ausdrücken weg.
Wie es funktioniert
Der Befehl besteht aus zwei Teilen, einem
grep
- und einemwc
Aufruf:## grep "^.{$( wc -L F )}$" F
Das
wc
wird in einer Prozesserweiterung verwendet$( ... )
, es wird also vorher ausgeführtgrep
. Es berechnet die Länge der längsten Linie. Die Shell-Erweiterungssyntax wird auf verwirrende Weise mit der Mustersyntax für reguläre Ausdrücke gemischt, daher werde ich die Prozesserweiterung auflösen:## wc -L F
42
## grep "^.{42}$" F
Hier wurde die Prozesserweiterung durch den Wert ersetzt, den sie zurückgeben würde, wodurch die verwendete
grep
Befehlszeile erstellt wurde. Wir können den regulären Ausdruck jetzt einfacher lesen: Er stimmt genau vom Anfang (^
) bis zum Ende ($
) der Zeile überein . Der Ausdruck zwischen ihnen stimmt mit jedem Zeichen außer Newline überein und wird 42 Mal wiederholt. Kombiniert sind das Zeilen, die aus genau 42 Zeichen bestehen.Nun zurück zu echten Shell-Befehlen: Die
grep
Option-E
(--extended-regexp
) erlaubt es, der{}
Lesbarkeit nicht zu entgehen . Option-m 1
(--max-count=1
) stoppt, nachdem die erste Zeile gefunden wurde. Der Befehl<
imwc
Befehl schreibt die Datei in das Standardverzeichnis, um zu verhindern, dasswc
der Dateiname zusammen mit der Länge gedruckt wird.Welche längsten Schlangen?
Um die Beispiele bei zweimaligem Auftreten des Dateinamens lesbarer zu machen, verwende ich eine Variable
f
für den Dateinamen. Jedes$f
im Beispiel könnte durch den Dateinamen ersetzt werden.Zeige die erste längste Zeile - die erste Zeile, die so lang ist wie die längste Zeile:
Zeige alle längsten Linien - alle Linien , die so lang wie die längste Linie sind:
Zeige die letzte längste Zeile - die letzte Zeile, die so lang ist wie die längste Zeile:
Zeigt die längste einzelne Zeile an - die längste Zeile ist länger als alle anderen Zeilen, oder schlägt fehl:
(Der letzte Befehl ist noch ineffizienter als die anderen, da er den vollständigen grep-Befehl wiederholt. Er sollte offensichtlich zerlegt werden, damit die Ausgabe von
wc
und die von geschriebenen Zeilengrep
in Variablen gespeichert werden.Beachten Sie, dass alle längsten Zeilen tatsächlich alle Zeilen sein können Zum Speichern in einer Variablen müssen nur die ersten beiden Zeilen beibehalten werden.)
quelle
Das folgende Beispiel sollte und sollte ein Kommentar zu dmitry.malikovs Antwort sein, aber wegen der unbrauchbaren Verwendung des sichtbaren Kommentarraums habe ich mich dazu entschieden, ihn hier zu präsentieren, wo er zumindest zu sehen sein wird. ..
Dies ist eine einfache Variation des von dmitry Single-Pass - Verfahren awk.
Es werden alle "gleich langen" Zeilen gedruckt. (Hinweis:
delete array
ist eine Gawk-Erweiterung).quelle
In reiner Bash:
quelle
_max_line[0]=${_line}
nicht den Rest aller zuvor angesammelten kürzeren "längsten Zeilen" ...unset _max_line
Ich habe dafür ein kleines Shell-Skript entwickelt. Es zeigt die Länge, die Zeilennummer und die Zeile selbst nach Länge an, die eine bestimmte Größe von 80 Zeichen überschreitet:
https://github.com/lordofrain/tools/blob/master/longest-line/longest-line.sh
quelle
$*
ist selten eine gute Idee, die Sie wollen"$@"
. Die/.*/
in Ihremawk
tut nichts, da dies auch mit Leerzeilen übereinstimmt. Sie könnten vermeiden, dem zu entkommen,\$0
wenn Sie das einfache Anführungszeichen verwenden'EOF'
. Warum einen leerenBEGIN{}
Block verwenden? Schließlich brauchen Sie nichtcat
, nurawk . . . "$file" | . . .
awk -vmax=15 '{len=length($0); if(len>=max){printf("%s, %d at line # %d %s\n", FILENAME, len, NR, $0);}}' file*
Sie können verwenden
wc
:quelle
wc -L
Nachteil.