Linha mais longa em um arquivo

198

Estou procurando uma maneira simples de encontrar o comprimento da linha mais longa em um arquivo. Idealmente, seria um simples comando bash shell em vez de um script.

Andrew Prock
fonte

Respostas:

270

Usando o wc (GNU coreutils) 7.4:

wc -L filename

dá:

101 filename
Daniel
fonte
56
Observe que apenas as -c -l -m -wopções são POSIX. -Lé um GNUism.
Jens
4
Observe também que o resultado de -Ldepende da localidade. Alguns caracteres (no sentido de bytes e multibytes) podem até não ser contados!
Walter Tross
7
OS X:wc: illegal option -- L usage: wc [-clmw] [file ...]
Hugo
12
OS X: usando homebrew, o uso gwc para GNU Palavra Conde gwc -L filename
kaycoder
3
O @xaxxon gwcestá na coreutilsfórmula, que instala todos os coreutils do GNU com um gprefixo.
gsnedders
100
awk '{print length, $0}' Input_file |sort -nr|head -1

Para referência: localizando a linha mais longa em um arquivo

Ponto azul pálido
fonte
12
Por que o comando cat extra? Apenas dê o nome do arquivo diretamente como argumento para o awk.
Thomas Padron-McCarthy
18
@Thomas. Expressá-lo como um canal é mais geral do que especificar um arquivo como uma opção. No meu caso, usarei a saída canalizada de uma consulta ao banco de dados.
31720 Andrew Prock
1
esta é a melhor resposta porque é mais POSIX (funciona bem no OS X)
MK.
5
@MK. No entanto, essa abordagem é O (n * log (n)) no número de linhas, enquanto a abordagem de Ramon é O (n).
jub0bs 04/09/2015
2
A classificação de um arquivo grande pode levar horas para ser concluída e consumir gigabytes, mesmo terabytes de espaço temporário, dependendo do tamanho do arquivo de entrada. Considere armazenar o maior comprimento e seu registro associado e imprimi-lo a partir de um END{}bloco.
Luv2code
67
awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }'  YOURFILE 
Ramon
fonte
3
awk '{ if (length($0) > max) max = length($0) } END { print max }' YOURFILE
2020
5
awk 'length>max{max=length}END{print max}' file
Chris Seymour
8
Esta resposta fornece o texto da linha mais longa do arquivo e não o seu comprimento. Estou deixando como está, embora a pergunta pergunte o comprimento, porque suspeito que será útil para as pessoas que acessam esta página apenas olhando para o título.
Ramon
3
Fácil de obter a contagem usando WC ..awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }' YOURFILE | wc -c
Nick
1
Você poderia explicar como isso funciona?
Lnux
23

Apenas para fins divertidos e educacionais, a solução shell POSIX pura , sem uso inútil de gato e sem bifurcação para comandos externos. Leva o nome do arquivo como primeiro argumento:

#!/bin/sh

MAX=0 IFS=
while read -r line; do
  if [ ${#line} -gt $MAX ]; then MAX=${#line}; fi
done < "$1"
printf "$MAX\n"
Jens
fonte
6
não poder ler de std in (via cat) na verdade reduz a utilidade disso, não a aprimora.
Andrew Prock
4
Bem, o OP disse explicitamente "arquivo" e sem o < "$1"pode facilmente ler do stdin. Com um teste $#, poderia até fazer as duas coisas, dependendo do número de argumentos. Simplesmente não há necessidade de gatos inúteis neste mundo. Iniciantes devem ser ensinados em conformidade desde o início.
Jens
7
Isso deve ter uma classificação mais alta, é o que o usuário pediu. Adicione a função longest () {MAX = 0 IFS = enquanto lê -r line; faça se [$ {# line} -gt $ MAX]; então MAX = $ {# line}; fi done echo $ MAX} à sua .bashrc e você pode executarlongest < /usr/share/dict/words
skierpage
13
wc -L < filename

101
Anônimo
fonte
1
Obrigado, eu estive procurando uma maneira de impedir wcde produzir o nome de arquivo :)
Peter.O
11
perl -ne 'print length()."  line $.  $_"' myfile | sort -nr | head -n 1

Imprime o comprimento, número da linha e conteúdo da linha mais longa

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

Imprime uma lista ordenada de todas as linhas, com números e comprimentos de linha

.é o operador de concatenação - é usado aqui depois que length ()
$.é o número
$_da linha atual é a linha atual

Chris Koknat
fonte
Requer a classificação de um arquivo. O desempenho seria terrível mesmo para arquivos de tamanho médio e não funcionará para arquivos maiores. wc -Lé a melhor solução que vi até agora.
Tagar
Usando um arquivo de texto 550MB 6.000.000 linha como a fonte (British National Corpus), a solução perl levou 12 segundos, enquanto wc -Llevou 3 segundos
Chris Koknat
wc -Lconte apenas os registros numéricos - esse Q estava prestes a encontrar a linha mais longa - não exatamente o mesmo, portanto, essa comparação não é precisa.
Tagar 26/09/17
6

Ponto negligenciado importante nos exemplos acima.

Os 2 exemplos a seguir contam guias expandidas

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

As 2 seguintes contam guias não expandidas.

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

tão

              Expanded    nonexpanded
$'nn\tnn'       10            5
John Kearney
fonte
5

Parece que toda a resposta não indica o número da linha mais longa. O comando a seguir pode fornecer o número da linha e o tamanho aproximado:

$ 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
fonte
Aqui vamos nós. Isso encontra meus comentários obnoxiously longos. Valeu cara.
Philip
Você poderia dar um passo adiante e eliminar o gato. awk '{print length}' test.txt | sort -rn | head -1. Se você precisa de conteúdo da linha atual é muito, então awk '{print length,$0}' test.txt | sort -k1 -rn| head -1
Kakoma
3

Em perl:

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

isso apenas imprime a linha, não o comprimento também.

rsp
fonte
3

Aqui estão as referências da resposta

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

http://wtanaka.com/node/7719

Nadir SOUALEM
fonte
1
O segundo script do awk apenas indica o comprimento mais longo, não mostra a linha mais longa.
rsp
1
Vamos lá .. Essas são as mesmas que as duas primeiras respostas adicionadas com as referências.
Pálido Ponto Azul
@rsp: eu mato a segunda resposta
Nadir SOUALEM 02/11/2009
2

Apenas por diversão, aqui está a versão do Powershell:

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

E para obter apenas o comprimento:

(cat filename.txt | sort length | select -last 1).Length
eddiegroves
fonte
4
Então, mesmo os programadores do PowerShell devem usar gatos inúteis?
Jens
1
@ Jens Não sei se entendi, o gato no Powershell é apenas um apelido para Get-Content, cujo comportamento depende do contexto e do provedor.
Eddegroves 22/09
Pode sortusar filename.txt como argumento? Então o gato é inútil porque sort length filename.txt | select -last 1evita um cano e um processo que apenas copia os dados.
Jens
Como nota de rodapé, o que exatamente é o PowerShell? Eu pensei que o utilitário powershell foi usado para máquinas Windows?
franklin
4
@ Jens, os dados frequentemente vêm de um fluxo em vez de um nome de arquivo. Este é um idioma padrão das ferramentas unix.
Andrew Prock
2

Estou em um ambiente Unix e trabalho com arquivos compactados com gzip de alguns GBs. Testei os seguintes comandos usando um arquivo compactado em gb de 2 GB com comprimento de registro de 2052.

  1. zcat <gzipped file> | wc -L

e

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

Os tempos estavam em média

  1. 117 segundos

  2. 109 segundos

Aqui está o meu script após cerca de 10 execuções.

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
fonte
Não tenho certeza se essa é uma comparação válida. Eu ficaria preocupado com o fato de a awkversão se beneficiar do armazenamento em cache do bloco de disco da wcversão que está sendo executada primeiro (e semear o cache do disco). Você precisaria aleatoriamente a ordem de quem é chamado primeiro nas dez execuções para fazer esse argumento continuar.
Chris Canonical
1

Variação sobre o tema.

Este mostrará todas as linhas com o comprimento da linha mais longa encontrada no arquivo, mantendo a ordem em que aparecem na fonte.

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

Então meu arquivo

x
mn
xyz
123
abc

darei

xyz
123
abc
Martin Clayton
fonte
0

Se você estiver usando o MacOS e estiver recebendo este erro: wc: illegal option -- L não é necessário instalar o GNU sipmly, faça isso.

Se tudo o que você deseja fazer é obter a contagem dos caracteres na linha mais longa do arquivo e você estiver usando a execução do OS X:

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

Algo assim;

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

Saídas:

The longest line in the file my_file has 117 characters

Ivansito87
fonte