Jak uzyskać najdłuższą linię z pliku?

10

Chciałbym znaleźć numer najdłuższej linii z pliku.

Na przykład, jeśli mam plik o następującej treści:

lalala
tatatata
abracadabra
mu mu mu

jak mogę napisać skrypt bash, który da mi wynik podobny do tego 3 -> abracadabra:?

użytkownik214965
źródło

Odpowiedzi:

9

Nie potrzebujesz do tego skryptu. Wystarczy proste polecenie:

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

Działa to nawet wtedy, gdy masz dwie lub więcej linii o tej samej maksymalnej długości.

Jeśli chcesz, aby wynik był dokładnie w tej formie 3 -> abracadabra:, użyj:

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

Bibliografia:

Radu Rădeanu
źródło
3
@ don.joey: taka jest siła unixa. Proste polecenia, które mogą współpracować. tutaj szuka „^. {n} $”, tj. dowolnej linii, która między początkiem linii ( ^) a końcem ( $) ma dokładnie n znaków ( .{n}). Potem musi tylko znaleźć n: do tego używa GNU-ism, „wc -L nazwa pliku” (zauważ, że to nie jest posiks), który zwraca długość najdłuższej linii nazwy pliku. Więc grepuje każdą linię, która ma najdłuższą długość. $(cmd)zastępuje się wynikiem cmd.
Olivier Dulac
1
@OlivierDulac Świetny komentarz.
Radu Rădeanu
Co więcej, możesz także dodać (np.) -C 3Do opcji grep, aby uzyskać kilka linii przed i po dla kontekstu
ShadSterling
8

Możesz użyć awkdo wydrukowania długości każdej linii ( length()) i numeru linii ( NR), a następnie odwrócić ( -r) sortwynik według liczby ( -n):

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

Aby wyświetlić tylko pierwszą linię:

$ awk '{ print length(), NR, $0 | "sort -rn" }' tmp.txt | head -n 1
10 3 abracadabr
Attila O.
źródło
@ user214965 proszę zobaczyć moją aktualizację, wyświetlany numer linii jest drugim numerem w wyniku.
Attila O.
Co jeśli są 2 linie o tej samej maksymalnej długości?
Radu Rădeanu
@ RaduRădeanu dobry punkt. +1 za wc -L, nie wiedziałem o tym argumencie. Jest to bardzo przydatne.
Attila O.
4

AO (N) można osiągnąć za pomocą wkładki perl one:

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

zastosowania (gdzie machin to nazwa pliku)

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

lub

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

lub (mniej wyraźny, ale krótszy)

perl -ne 'if(length>length$m){$m=$_};END{print$m}' machin
MUY Belgium
źródło
Znacznie bardziej wydajne. Dzięki! Szukałem tego.
test30
1
Działa z dużymi plikami +1
h3xStream
0

O (n) W przypadku maszyn, na przykład OpenWRT, gdzie perl nie jest dostępny, @ awk @ wersja może być przydatna.

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

lub python:

python -c "print max(open('$file', 'r'), key=len)"
test30
źródło
0

Odpowiedź Radu jest całkowicie wystarczająca i preferowana, chociaż jeśli chcesz bardziej jednoznacznego rozwiązania opartego na powłoce, możesz użyć następującego skryptu:

#!/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}"

Stosowanie: ./find_longest.sh input.txt

Przykład:

$ 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
Sergiy Kolodyazhnyy
źródło