Estoy buscando el método más simple para imprimir la línea más larga en un archivo. Busqué en Google y sorprendentemente no pude encontrar una respuesta. Con frecuencia imprimo la longitud de la línea más larga en un archivo, pero no sé cómo imprimir realmente la línea más larga. ¿Alguien puede proporcionar una solución para imprimir la línea más larga en un archivo? Gracias por adelantado.
35
Respuestas:
UPD : resumiendo todos los consejos en los comentarios
fuente
cat
) como usar una tubería son operaciones costosas, sin mencionar que es más eficiente para awk simplemente leer el archivo. Las implicaciones de rendimiento son definitivamente notables si esto se hace con frecuencia, y aun así, está haciendo un mal uso por completocat
.cat
no es inútil aquí. Puede ser inútil para una computadora, pero para un lector humano podría proporcionar valor. La primera variante muestra claramente la entrada. El flujo es más natural (de izquierda a derecha). En el segundo caso, no sabe cuál es la entrada a menos que desplace la ventana.cat
.< file command
funciona bien< filename command
es equivalente afilename < command
en cada shell que he probado. Pero una vez que lo sepa, puede aprovecharlo al escribir tuberías largas que muestren claramente la dirección del flujo de datos (sin invocar un comando adicional):< input-file command1 | command2 | command3 > output-file
fuente
Esto lee primero el archivo dentro de la sustitución del comando y genera la longitud de la línea más larga (anteriormente,
expand
convierte las pestañas en espacios, para superar la semántica dewc -L
- cada pestaña en la línea agregará 8 en lugar de 1 a la longitud de la línea). Esta longitud se usa en unased
expresión que significa "encontrar una línea de este número de caracteres, imprimirla y salir". Entonces, en realidad, esto puede ser tan óptimo como la línea más larga está cerca de la parte superior del archivo, jeje (gracias por los comentarios impresionantes y constructivos).Otro, había pensado antes que el sed (en bash):
fuente
-L, --max-line-length
imprime la longitud de la línea más larga, de acuerdo con la página del manual, pero si profundiza (como cuando obtiene resultados incorrectos / inesperados ), encontrará que esta opción incrementa la longitud en 8 por cada 1 pestaña de caracteres\x09
ver este Q / A de Unix y Linuxsed -rn "/.{$(<file expand -t1 |wc -L)}/p" file
read line
interpretará caracteres escapados como el carbón literal, por ejemplo\A
resloves aA
, que por supuesto efectivamente informa de un corto que real de bytes en el uso ... Para evitar esto escapado interpretación, utilice:read -r line
. . . . Además, para cerrar la versión sed + wc después de la primera "línea más larga", cambiep
a{p;q}
...sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file
Aquí hay una solución de Perl:
O, si desea imprimir todas las líneas más largas
Como no tenía nada mejor que hacer, ejecuté algunos puntos de referencia en un archivo de texto 625M. Sorprendentemente, mi solución Perl fue consistentemente más rápida que las otras. Por supuesto, la diferencia con lo aceptado
awk
solución es pequeña, pero está ahí. Obviamente, las soluciones que imprimen varias líneas son más lentas, así que las he ordenado por tipo, de la más rápida a la más lenta.Imprima solo una de las líneas más largas:
Imprima todas las líneas más largas:
fuente
Grep la primera línea más larga
El comando es inusualmente difícil de leer sin práctica porque mezcla la sintaxis de shell y regexp.
Para explicación, usaré pseudocódigo simplificado primero. Las líneas que comienzan con
##
no se ejecutan en el shell.Este código simplificado usa el nombre de archivo F y deja de lado las comillas y partes de expresiones regulares para facilitar la lectura.
Cómo funciona
El comando tiene dos partes, una
grep
- y unawc
invocación:## grep "^.{$( wc -L F )}$" F
Se
wc
utiliza en una expansión de proceso$( ... )
, por lo que se ejecuta antesgrep
. Calcula la longitud de la línea más larga. La sintaxis de expansión de shell se mezcla con la sintaxis del patrón de expresión regular de una manera confusa, por lo que descompondré la expansión del proceso:## wc -L F
42
## grep "^.{42}$" F
Aquí, la expansión del proceso se reemplazó con el valor que devolvería, creando la
grep
línea de comando que se utiliza. Ahora podemos leer la expresión regular más fácilmente: coincide exactamente desde el inicio (^
) hasta el final ($
) de la línea. La expresión entre ellos coincide con cualquier carácter, excepto la nueva línea, que se repite 42 veces. Combinados, es decir, líneas que consisten en exactamente 42 caracteres.Ahora, volviendo a los comandos de shell reales: la
grep
opción-E
(--extended-regexp
) permite no escapar de la{}
legibilidad. La opción-m 1
(--max-count=1
) hace que se detenga después de encontrar la primera línea. El<
en elwc
comando escribe el archivo en su stdin, para evitarwc
imprimir el nombre del archivo junto con la longitud.¿Qué líneas más largas?
Para hacer que los ejemplos sean más legibles con el nombre de archivo que ocurre dos veces, usaré una variable
f
para el nombre de archivo; Cada uno$f
en el ejemplo podría ser reemplazado por el nombre del archivo.Mostrar la primera línea más larga : la primera línea que es tan larga como la línea más larga:
Mostrar todas las líneas más largas : todas las líneas que son tan largas como la línea más larga:
Mostrar la última línea más larga : la última línea que es tan larga como la línea más larga:
Mostrar la línea más larga individual : la línea más larga más larga que todas las demás líneas, o falla:
(El último comando es aún más ineficiente que los demás, ya que repite el comando grep completo. Obviamente, debe descomponerse para que la salida
wc
y las líneas escritas porgrep
se guarden en las variables.Tenga en cuenta que todas las líneas más largas pueden ser todas líneas Para guardar en una variable, solo se deben mantener las dos primeras líneas).
fuente
El siguiente ejemplo iba a ser, y debería haber sido, un comentario a la respuesta de dmitry.malikov , pero debido al uso inútil del espacio visible de comentarios allí, he elegido presentarlo aquí, donde al menos se verá. ..
Esta es una variación simple del método awk de paso único de dmitry .
Imprime todas las líneas "iguales más largas". (Nota:
delete array
es una extensión gawk).fuente
En puro golpe:
fuente
_max_line[0]=${_line}
no elimina el resto de las "líneas más largas" más cortas previamente acumuladas ...unset _max_line
borrará toda la matriz ...He desarrollado un pequeño script de shell para esto. Muestra la longitud, el número de línea y la línea por longitud que excede un tamaño particular como 80 caracteres:
https://github.com/lordofrain/tools/blob/master/longest-line/longest-line.sh
fuente
$*
rara vez es una buena idea, que desea"$@"
. El/.*/
en suawk
no hace nada ya que también coincide con líneas vacías. Podrías evitar escapar de la\$0
cita simple'EOF'
. ¿Por qué usar unBEGIN{}
bloque vacío ? Finalmente, no necesitacat
, soloawk . . . "$file" | . . .
awk -vmax=15 '{len=length($0); if(len>=max){printf("%s, %d at line # %d %s\n", FILENAME, len, NR, $0);}}' file*
Puedes usar
wc
:fuente
wc -L
el inconveniente de.