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.catno 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 commandfunciona bien< filename commandes equivalente afilename < commanden 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-filefuente
Esto lee primero el archivo dentro de la sustitución del comando y genera la longitud de la línea más larga (anteriormente,
expandconvierte 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 unasedexpresió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-lengthimprime 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\x09ver este Q / A de Unix y Linuxsed -rn "/.{$(<file expand -t1 |wc -L)}/p" fileread lineinterpretará caracteres escapados como el carbón literal, por ejemplo\Aresloves 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", cambiepa{p;q}...sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" fileAquí 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
awksolució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 unawcinvocación:## grep "^.{$( wc -L F )}$" FSe
wcutiliza 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 F42## grep "^.{42}$" FAquí, la expansión del proceso se reemplazó con el valor que devolvería, creando la
greplí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
grepopció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 elwccomando escribe el archivo en su stdin, para evitarwcimprimir 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
fpara el nombre de archivo; Cada uno$fen 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
wcy las líneas escritas porgrepse 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 arrayes 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_lineborrará 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 suawkno hace nada ya que también coincide con líneas vacías. Podrías evitar escapar de la\$0cita 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 -Lel inconveniente de.