Wie erhalte ich die längste Zeile aus einer Datei?


10

Ich bin daran interessiert, die Zeilennummer der längsten Zeile aus einer Datei herauszufinden.

Zum Beispiel, wenn ich eine Datei mit folgendem Inhalt habe:

lalala
tatatata
abracadabra
mu mu mu

Wie kann ich ein Bash-Skript schreiben, das mir eine Ausgabe wie folgt gibt : 3 -> abracadabra?

Antworten:


9

Sie benötigen dazu kein Skript. Ein einfacher Befehl reicht aus:

egrep -n "^.{$(wc -L < filename)}$" filename

Dies funktioniert auch dann, wenn Sie zwei oder mehr Zeilen mit derselben maximalen Länge haben.

Wenn die Ausgabe genau in dieser Form vorliegen soll 3 -> abracadabra, verwenden Sie:

egrep -n "^.{$(wc -L < filename)}$" filename | sed 's/:/ -> /'

Verweise:


3
@ don.joey: das ist die Macht von Unix. Einfache Befehle, die zusammenarbeiten können. hier sucht er nach "^. {n} $", dh nach jeder Zeile, die zwischen dem Anfang der Zeile ( ^) und ihrem Ende ( $) genau n Zeichen ( .{n}) hat. Dann muss er nur noch n finden: Dafür verwendet er einen GNU-Ismus, "wc -L Dateiname" (beachten Sie, dass dies kein Posix ist), der die Länge der längsten Zeile des Dateinamens zurückgibt. Also greift er nach jeder Zeile mit der längsten Länge. $(cmd)wird durch die Ausgabe von ersetzt cmd.
Olivier Dulac

1
@OlivierDulac Großartiger Kommentar.
Radu Rădeanu

Noch besser ist, dass Sie -C 3den grep-Optionen auch (z. B.) hinzufügen können, um ein paar Zeilen vor und nach dem Kontext zu erhalten
ShadSterling

8

Sie könnten nutzen awkdie Länge jeder Zeile (drucken length()) und die Zeilennummer ( NR), dann rückwärts ( -r) sortdas Ergebnis durch die Anzahl ( -n):

$ awk '{ print length(), NR, $0 | "sort -rn" }' tmp.txt
10 3 abracadabr
8 4 mu mu mu
7 2 tatatat
6 1 lalala

Um nur die erste Zeile anzuzeigen:

$ awk '{ print length(), NR, $0 | "sort -rn" }' tmp.txt | head -n 1
10 3 abracadabr

@ user214965 siehe mein Update, die angezeigte Zeilennummer ist die zweite Nummer im Ergebnis.
Attila O.

Was ist, wenn 2 Zeilen mit derselben maximalen Länge vorhanden sind?
Radu Rădeanu

@ RaduRădeanu guter Punkt. +1 für wc -L, ich wusste nichts über dieses Argument. Es ist in der Tat sehr nützlich.
Attila O.

4

AO (N) kann mit einem Perl One Liner erreicht werden:

perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max'

Verwendungen (wobei machin ein Dateiname ist)

cat machin | perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max'

oder

perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max' machin

oder (weniger klar, aber kürzer)

perl -ne 'if(length>length$m){$m=$_};END{print$m}' machin

Viel, viel effizienter. Vielen Dank! Ich habe danach gesucht.
Test30

1
Funktioniert mit riesigen Dateien +1
h3xStream

0

O (n) Für Computer, z. B. OpenWRT, auf denen Perl nicht verfügbar ist, kann die Version @ awk @ hilfreich sein.

awk 'length > l {l=length;line=$0} END {print line}' FILE

oder Python:

python -c "print max(open('$file', 'r'), key=len)"

0

Radus Antwort ist vollkommen ausreichend und wird bevorzugt. Wenn Sie jedoch eine explizitere und Shell-basierte Lösung wünschen, können Sie das folgende Skript verwenden:

#!/bin/bash
longest_length=0
longest_string=0
while IFS= read -r line || [ -n "${line}"]
do
    if [ "${#line}" -gt "${longest_length}" ]
    then
        longest_length="${#line}"
        longest_string="$line"
    fi
done < "$1"

echo "${longest_string}"

Verwendungszweck: ./find_longest.sh input.txt

Beispiel:

$ cat input.txt                                                          
1 2 
2 3 a a a a
4 5 6 
1 1 1 5

$ ./find_longest.sh input.txt                                            
2 3 a a a a
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.