Najdłuższa linia w pliku

198

Szukam prostego sposobu znalezienia długości najdłuższej linii w pliku. Idealnie byłoby to proste polecenie powłoki bash zamiast skryptu.

Andrew Prock
źródło

Odpowiedzi:

270

Korzystanie z wc (GNU coreutils) 7.4:

wc -L filename

daje:

101 filename
Daniel
źródło
56
Pamiętaj, że tylko -c -l -m -wopcje to POSIX. -Lto GNUism.
Jens
4
Pamiętaj również, że wynik -Lzależy od ustawień regionalnych. Niektóre znaki (zarówno bajtowe, jak i wielobajtowe) mogą nawet nie być liczone!
Walter Tross,
7
OS X:wc: illegal option -- L usage: wc [-clmw] [file ...]
Hugo
12
OS X: używanie homebrew, użyj GWC dla GNU wyrazów GWC -L filename
kaycoder
3
@xaxxon gwcjest w coreutilsformule, która instaluje wszystkie jądra GNU z gprefiksem.
gsnedders
100
awk '{print length, $0}' Input_file |sort -nr|head -1

Dla odniesienia: Znajdowanie najdłuższej linii w pliku

Blada niebieska kropka
źródło
12
Dlaczego dodatkowe polecenie kota? Podaj nazwę pliku bezpośrednio jako argument dla awk.
Thomas Padron-McCarthy
18
@Tomasz. Wyrażenie go jako potoku jest bardziej ogólne niż określenie pliku jako opcji. W moim przypadku użyję danych wyjściowych z zapytania do bazy danych.
Andrew Prock,
1
ten jest najlepszą odpowiedzią, ponieważ jest bardziej POSIX (cóż, działa na OS X)
MK.
5
@MK. Jednak podejście to jest O (n * log (n)) w liczbie linii, podczas gdy podejście Ramona to O (n).
jub0bs,
2
Sortowanie dużego pliku może zająć wiele godzin, a skompletowanie i zużywanie gigabajtów, a nawet terabajtów przestrzeni tymczasowej, zależy od wielkości pliku wejściowego. Rozważ zapisanie najdłuższej długości i związanego z nią rekordu, a następnie wydrukowanie go z END{}bloku.
Luv2code
67
awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }'  YOURFILE 
Ramon
źródło
3
awk '{ if (length($0) > max) max = length($0) } END { print max }' YOURFILE
ke20
5
awk 'length>max{max=length}END{print max}' file
Chris Seymour,
8
Ta odpowiedź podaje tekst najdłuższej linii w pliku, a nie jego długość. Zostawiam bez zmian, chociaż pytanie dotyczy długości, ponieważ podejrzewam, że przyda się osobom, które odwiedzą tę stronę, patrząc tylko na tytuł.
Ramon
3
Łatwo uzyskać policzenie za pomocą WC ..awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }' YOURFILE | wc -c
Nick
1
Czy mógłbyś wyjaśnić, jak to działa?
Lnux,
23

Tylko dla zabawy i celów edukacyjnych, czyste rozwiązanie powłoki POSIX , bez zbędnego korzystania z cat i bez wybierania poleceń zewnętrznych. Pierwszym argumentem jest nazwa pliku:

#!/bin/sh

MAX=0 IFS=
while read -r line; do
  if [ ${#line} -gt $MAX ]; then MAX=${#line}; fi
done < "$1"
printf "$MAX\n"
Jens
źródło
6
brak możliwości odczytu ze standardowego wejścia (przez cat) faktycznie zmniejsza użyteczność tego, a nie zwiększa.
Andrew Prock,
4
Cóż, OP wyraźnie powiedział „plik” i bez < "$1"niego można łatwo odczytać ze standardowego wejścia. Z testem $#może to zrobić oba, w zależności od liczby argumentów. Po prostu nie ma potrzeby zbędnych kotów na tym świecie. Początkujących należy uczyć odpowiednio od samego początku.
Jens
7
To powinno być ocenione wyżej, to jest to, o co poprosił użytkownik. Dodaj funkcję najdłużej () {MAX = 0 IFS = podczas odczytu -r linii; zrobić, jeśli [$ {# linia} -gt $ MAX]; następnie MAX = $ {# linia}; fi gotowe echo $ MAX} na .bashrc i możesz biegaćlongest < /usr/share/dict/words
skierpage 12.12
13
wc -L < filename

daje

101
Anonimowy
źródło
1
Dzięki, szukałem sposobu, aby zapobiec wcwysyłaniu nazwy pliku :)
Peter.O
11
perl -ne 'print length()."  line $.  $_"' myfile | sort -nr | head -n 1

Drukuje długość, numer linii i zawartość najdłuższej linii

perl -ne 'print length()."  line $.  $_"' myfile | sort -n

Drukuje posortowaną listę wszystkich linii z numerami i długościami linii

.jest operatorem konkatenacji - używa się go tutaj po length (),
$.gdzie bieżący numer linii
$_jest bieżącą linią

Chris Koknat
źródło
Wymaga sortowania pliku. Wydajność byłaby straszna nawet dla plików średniej wielkości i nie działałaby dla większych plików. wc -Lto najlepsze rozwiązanie, jakie do tej pory widziałem.
Tagar
Używając 550 MB 6 000 000 liniowego pliku tekstowego jako źródła (British National Corpus), rozwiązanie perla zajęło 12 sekund, podczas gdy wc -L3 sekundy
Chris Koknat
wc -Lwystarczy policzyć rekordy liczb - to Q miało znaleźć najdłuższą linię - niezupełnie takie same, więc nie jest to dokładne porównanie.
Tagar
6

Ważny przeoczony punkt w powyższych przykładach.

Poniższe 2 przykłady zawierają rozwinięte karty

  wc -L  <"${SourceFile}" 
# or
  expand --tabs=8 "${SourceFile}" | awk '{ if (length($0) > max) {max = length($0)} } END { print max }'

Poniższe 2 liczą nie rozwinięte karty.

  expand --tabs=1 "${SourceFile}" | wc -L 
# or
  awk '{ if (length($0) > max) {max = length($0)} } END { print max }' "${SourceFile}"

więc

              Expanded    nonexpanded
$'nn\tnn'       10            5
John Kearney
źródło
5

Wygląda na to, że odpowiedź nie podaje numeru najdłuższej linii. Następujące polecenie może podać numer linii i z grubsza długość:

$ cat -n test.txt | awk '{print "longest_line_number: " $1 " length_with_line_number: " length}' | sort -k4 -nr | head -3
longest_line_number: 3 length_with_line_number: 13
longest_line_number: 4 length_with_line_number: 12
longest_line_number: 2 length_with_line_number: 11
wangf
źródło
No to jedziemy. To znajduje moje nieznośnie długie komentarze. Dzięki stary.
Philip,
Możesz pójść o krok dalej i wyeliminować kota. awk '{print length}' test.txt | sort -rn | head -1. Jeśli potrzebujesz także rzeczywistej zawartości linii, to awk '{print length,$0}' test.txt | sort -k1 -rn| head -1
kakoma
3

W perlu:

perl -ne 'print ($l = $_) if (length > length($l));' filename | tail -1

to tylko drukuje linię, a nie jej długość.

rsp
źródło
3

Oto odniesienia do odpowiedzi

cat filename | awk '{print length, $0}'|sort -nr|head -1

http://wtanaka.com/node/7719

Nadir SOUALEM
źródło
1
Ten drugi skrypt awk powie ci tylko najdłuższą długość, a nie pokaż najdłuższą linię.
rsp
1
Chodź .. Są to te same, co dwie pierwsze odpowiedzi dodane do referencji.
Jasnoniebieska kropka
@rsp: zabijam drugiego
anwsera
2

Dla zabawy, oto wersja Powershell:

cat filename.txt | sort length | select -last 1

I po prostu uzyskać długość:

(cat filename.txt | sort length | select -last 1).Length
eddiegroves
źródło
4
Więc nawet programiści PowerShell muszą używać bezużytecznych kotów?
Jens
1
@Jens Nie jestem pewien, czy cię rozumiem, cat in Powershell to tylko alias dla Get-Content, którego zachowanie zależy od kontekstu i dostawcy.
eddiegroves,
Czy sortjako argument można wziąć plik filename.txt? Wtedy kot jest bezużyteczny, ponieważ sort length filename.txt | select -last 1unika potoku i procesu, który po prostu kopiuje dane.
Jens
Na marginesie, czym właściwie jest PowerShell? Myślałem, że narzędzie PowerShell było używane do komputerów z systemem Windows?
franklin
4
@Jens, dane często pochodzą ze strumienia zamiast nazwy pliku. Jest to standardowy idiom narzędzi uniksowych.
Andrew Prock,
2

Jestem w środowisku Unix i pracuję z plikami spakowanymi gzipem o wielkości kilku GB. Przetestowałem następujące polecenia, używając 2 gzipowanego pliku o długości rekordu 2052.

  1. zcat <gzipped file> | wc -L

i

  1. zcat <gzipped file> | awk '{print length}' | sort -u

Czasy były na średnim poziomie

  1. 117 sekund

  2. 109 sekund

Oto mój skrypt po około 10 uruchomieniach.

START=$(date +%s) ## time of start

zcat $1 |  wc -L

END=$(date +%s) ## time of end
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"

START=$(date +%s) ## time of start

zcat $1 |  awk '{print length}' | sort -u

END=$(date +%s) ## time of end
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"
Jon
źródło
Nie jestem pewien, czy jest to prawidłowe porównanie, martwiłbym się, że awkwersja korzysta z buforowania bloków dysku dla wcwersji, która jest uruchomiona jako pierwsza (i inicjuje pamięć podręczną dysku). Będziesz musiał losowo uporządkować, kto zostanie wywołany jako pierwszy w ciągu dziesięciu przebiegów, aby utrzymać ten argument.
Canonical Chris
1

Wariacja na temat.

Ten pokaże wszystkie linie mające długość najdłuższej linii znalezionej w pliku, zachowując kolejność, w jakiej pojawiają się w źródle.

FILE=myfile grep `tr -c "\n" "." < $FILE | sort | tail -1` $FILE

Więc mój plik

x
mn
xyz
123
abc

da

xyz
123
abc
Martin Clayton
źródło
0

Jeśli używasz MacOS i wc: illegal option -- Lpojawia się ten błąd: nie musisz instalować GNU sipmly, zrób to.

Jeśli wszystko, co chcesz zrobić, to po prostu uzyskać liczbę znaków w najdłuższej linii pliku i używasz OS X run:

awk '{print length}' "$file_name" | sort -rn | head -1

Coś takiego;

echo "The longest line in the file $file_name has $(awk '{print length}' "$file_name" | sort -rn | head -1) characters"

Wyjścia:

The longest line in the file my_file has 117 characters

Ivansito87
źródło