Como obter a linha mais longa de um arquivo?

10

Estou interessado em descobrir o número da linha mais longa de um arquivo.

Por exemplo, se eu tiver um arquivo com o seguinte conteúdo:

lalala
tatatata
abracadabra
mu mu mu

como posso escrever um script bash que me dará uma saída parecida com esta 3 -> abracadabra:?

user214965
fonte

Respostas:

9

Você não precisa de um script para fazer isso. Um comando simples é suficiente:

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

Isso funcionará mesmo quando você tiver duas ou mais linhas com o mesmo comprimento máximo.

Se você deseja que a saída esteja exatamente neste formato 3 -> abracadabra:, use:

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

Referências:

Radu Rădeanu
fonte
3
@ don.joey: esse é o poder do unix. Comandos simples, que podem trabalhar juntos. aqui, ele procura por "^. {n} $", ou seja, qualquer linha que, entre o início da linha ( ^) e o final ( $), tenha exatamente n caracteres ( .{n}). Então ele só precisa encontrar n: para isso, ele usa um GNU-ism, "wc -L filename" (observe que este não é posix), que retorna o comprimento da linha mais longa do nome do arquivo. Então ele cumprimenta qualquer linha que tenha o maior comprimento. $(cmd)é substituído pela saída de cmd.
precisa
11
@OlivierDulac Ótimo comentário.
Radu Rădeanu
Ainda melhor, você também pode adicionar (por exemplo) -C 3às opções grep para obter algumas linhas antes e depois do contexto
ShadSterling 14/03
8

Você pode usar awkpara imprimir o comprimento de cada linha ( length()) e o número da linha ( NR) e inverter ( -r) sorto resultado pelo número ( -n):

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

Para mostrar apenas a primeira linha:

$ awk '{ print length(), NR, $0 | "sort -rn" }' tmp.txt | head -n 1
10 3 abracadabr
Attila O.
fonte
@ user214965, veja minha atualização; o número da linha exibida é o segundo número no resultado.
Attila O.
E se houver duas linhas com o mesmo comprimento máximo?
Radu Rădeanu
@ RaduRădeanu bom ponto. +1 por wc -L, eu não sabia sobre esse argumento. É realmente muito útil.
Attila O.
4

AO (N) pode ser alcançado com um liner perl one:

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

usos (em que machin é um nome de arquivo)

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

ou

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

ou (menos claro, mas mais curto)

perl -ne 'if(length>length$m){$m=$_};END{print$m}' machin
MUY Bélgica
fonte
Muito, muito mais eficiente. Obrigado! Estava procurando por isso.
test30
11
Funciona com arquivos enormes +1
h3xStream 29/10
0

O (n) Para máquinas, por exemplo, OpenWRT, em que o perl não está disponível, a versão @ awk @ pode ser útil.

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

ou python:

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

A resposta de Radu é perfeitamente suficiente e preferida, embora se você quiser uma solução mais explícita e baseada em shell, use o seguinte script:

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

Uso: ./find_longest.sh input.txt

Exemplo:

$ 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
fonte