Línea más larga en un archivo

198

Estoy buscando una manera simple de encontrar la longitud de la línea más larga en un archivo. Idealmente, sería un simple comando bash shell en lugar de un script.

Andrew Prock
fuente

Respuestas:

270

Usando wc (GNU coreutils) 7.4:

wc -L filename

da:

101 filename
Daniel
fuente
56
Tenga en cuenta que solo las -c -l -m -wopciones son POSIX. -LEs un GNUismo.
Jens
44
Tenga en cuenta también que el resultado de -Ldepende de la configuración regional. ¡Algunos caracteres (tanto en el byte como en el sentido multibyte) pueden incluso no contarse en absoluto!
Walter Tross
77
OS X:wc: illegal option -- L usage: wc [-clmw] [file ...]
Hugo
12
OS X: usando homebrew, use gwc para GNU Word Count gwc -L filename
kaycoder
3
@xaxxon gwcestá en la coreutilsfórmula, que instala todos los coreutils de GNU con un gprefijo.
gsnedders
100
awk '{print length, $0}' Input_file |sort -nr|head -1

Como referencia: encontrar la línea más larga en un archivo

Pálido punto azul
fuente
12
¿Por qué el comando extra cat? Simplemente proporcione el nombre del archivo directamente como argumento para awk.
Thomas Padron-McCarthy
18
@Thomas. Expresarlo como una tubería es más general que especificar un archivo como una opción. En mi caso, usaré la salida canalizada desde una consulta de base de datos.
Andrew Prock
1
esta es la mejor respuesta porque es más POSIX (bueno, funciona en OS X)
MK.
55
@MK. Sin embargo, este enfoque es O (n * log (n)) en el número de líneas, mientras que el enfoque de Ramon es O (n).
jub0bs
2
La clasificación de un archivo grande puede tardar horas en completarse y consumir gigabytes, incluso terabytes de espacio temporal, dependiendo del tamaño del archivo de entrada. Considere almacenar la longitud más larga y su registro asociado, luego imprímalo desde un END{}bloque.
Luv2code del
67
awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }'  YOURFILE 
Ramon
fuente
3
awk '{ if (length($0) > max) max = length($0) } END { print max }' YOURFILE
ke20
55
awk 'length>max{max=length}END{print max}' file
Chris Seymour
8
Esta respuesta proporciona el texto de la línea más larga del archivo en lugar de su longitud. Lo dejo como está, a pesar de que la pregunta pide la extensión porque sospecho que será útil para las personas que vienen a esta página simplemente mirando el título.
Ramon
3
Fácil de contar con WC.awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }' YOURFILE | wc -c
Nick
1
¿Podría explicarnos cómo funciona esto?
Lnux
23

Solo por diversión y con fines educativos, la solución de shell POSIX pura , sin uso inútil de cat y sin bifurcación a comandos externos. Toma el nombre de archivo como primer 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
fuente
66
no poder leer desde std in (a través de cat) en realidad reduce la utilidad de esto, no la mejora.
Andrew Prock
44
Bueno, el OP dijo explícitamente "archivo" y sin el < "$1"puede leer fácilmente desde stdin. Con una prueba $#incluso podría hacer ambas cosas, dependiendo de la cantidad de args. Simplemente no hay necesidad de gatos inútiles en este mundo. Los novatos deben ser enseñados en consecuencia desde el principio.
Jens
77
Esto debería tener una calificación más alta, es lo que solicitó el usuario. Agregue la función más larga () {MAX = 0 IFS = mientras lee -r línea; hacer si [$ {# line} -gt $ MAX]; entonces MAX = $ {# line}; fi done echo $ MAX} a tu .bashrc y puedes ejecutarlolongest < /usr/share/dict/words
skierpage
13
wc -L < filename

da

101
Anónimo
fuente
1
Gracias, he estado buscando una manera de evitar que wcel nombre de archivo
salga
11
perl -ne 'print length()."  line $.  $_"' myfile | sort -nr | head -n 1

Imprime la longitud, el número de línea y el contenido de la línea más larga.

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

Imprime una lista ordenada de todas las líneas, con números y longitudes de línea.

.es el operador de concatenación: se usa aquí después de length ()
$.es el número de línea actual
$_es la línea actual

Chris Koknat
fuente
Requiere ordenar un archivo ... el rendimiento sería terrible incluso para archivos de tamaño moderado y no funcionará para archivos más grandes. wc -LEs la mejor solución que vi hasta ahora.
Tagar
Usando un archivo de texto de 550,000 6,000,000 líneas como fuente (British National Corpus), la solución de perl tomó 12 segundos, mientras que wc -Ltomó 3 segundos
Chris Koknat
wc -Lsolo cuente los registros de números: esta Q estaba a punto de encontrar la línea más larga , no es exactamente lo mismo, por lo que esta no es una comparación precisa.
Tagar
6

Punto importante pasado por alto en los ejemplos anteriores.

Los siguientes 2 ejemplos cuentan pestañas expandidas

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

Los siguientes 2 cuentan pestañas no expandidas.

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

entonces

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

Parece que todas las respuestas no dan el número de línea de la línea más larga. El siguiente comando puede dar el número de línea y la longitud aproximada:

$ 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
fuente
Aquí vamos. Eso encuentra mis comentarios odiosamente largos. Gracias amigo
Philip
Podría llevar esto un paso más allá y eliminar al gato. awk '{print length}' test.txt | sort -rn | head -1. Si también necesita el contenido real de la línea, entonces awk '{print length,$0}' test.txt | sort -k1 -rn| head -1
kakoma
3

En perl:

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

esto solo imprime la línea, no su longitud también.

rsp
fuente
3

Aquí hay referencias de la respuesta

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

http://wtanaka.com/node/7719

Nadir SOUALEM
fuente
1
Ese segundo script awk solo te dirá la longitud más larga, no mostrará la línea más larga.
rsp
1
Vamos ... Son las mismas dos respuestas agregadas con las referencias.
Pale Blue Dot el
@rsp: mato al segundo respondedor
Nadir SOUALEM
2

Solo por diversión, aquí está la versión Powershell:

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

Y solo para obtener la longitud:

(cat filename.txt | sort length | select -last 1).Length
Eddiegroves
fuente
44
Entonces, ¿incluso los programadores de PowerShell deben usar gatos inútiles?
Jens
1
@Jens No estoy seguro de entenderte, cat en Powershell es solo un alias para Get-Content, cuyo comportamiento depende del contexto y el proveedor.
eddiegroves
¿Puede sorttomar filename.txt como argumento? Entonces el gato es inútil porque sort length filename.txt | select -last 1evita una tubería y un proceso que simplemente copia datos.
Jens
Como nota al margen, ¿qué es exactamente PowerShell? ¿Pensé que la utilidad powershell se usaba para máquinas Windows?
franklin
44
@Jens, los datos con frecuencia provienen de una secuencia en lugar de un nombre de archivo. Este es un lenguaje de herramientas estándar de Unix.
Andrew Prock
2

Estoy en un entorno Unix y trabajo con archivos comprimidos que tienen un tamaño de unos pocos GB. Probé los siguientes comandos usando un archivo comprimido de 2 GB con una longitud de registro de 2052.

  1. zcat <gzipped file> | wc -L

y

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

Los tiempos estaban en una avarage

  1. 117 segundos

  2. 109 segundos

Aquí está mi script después de aproximadamente 10 ejecuciones.

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
fuente
No estoy seguro de que sea una comparación válida, me preocuparía que la awkversión se beneficie del almacenamiento en caché del bloque de disco de la wcversión que se está ejecutando primero (y genera la memoria caché del disco). Tendría que aleatorizar el orden de quién llama primero durante las diez carreras para que este argumento se mantenga.
Canonical Chris
1

Variación sobre el tema.

Este mostrará todas las líneas que tengan la longitud de la línea más larga encontrada en el archivo, conservando el orden en que aparecen en la fuente.

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

Entonces mi archivo

x
mn
xyz
123
abc

daré

xyz
123
abc
Martin Clayton
fuente
0

Si está utilizando MacOS y obtiene este error: wc: illegal option -- Lno necesita instalar GNU sipmly, haga esto.

Si todo lo que quiere hacer es obtener el recuento de los caracteres en la línea más larga del archivo y está utilizando OS X run:

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

Algo como esto;

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

Salidas:

The longest line in the file my_file has 117 characters

Ivansito87
fuente