¿Cómo puedo identificar líneas en archivos de una longitud determinada?


12

Me gustaría encontrar líneas en mi código que excedan una cierta longitud. Mi código está en múltiples archivos. ¿Cuál es una buena manera de hacer esto?

Me gustaría saber los archivos y los números de línea; el contenido sería preferido, pero no necesario. El propósito del ejercicio es descubrir cómo romper las líneas (probablemente de forma manual).


¿Cómo quieres los resultados? ¿Como las líneas en sí (su contenido, como en grep), o como números de línea, o como algo más (tal vez desee aplicar otra acción sobre ellas)? Probablemente, la forma más conveniente de hacerlo depende de lo que se haga con estas líneas a continuación.
imz - Ivan Zakharyaschev

@ imz - IvanZakharyaschev Buen punto. Pregunta actualizada
Marcin

Respuestas:


13

Con grep:

grep -En '.{12}' file

Para líneas de al menos 12 caracteres de longitud.

Con varios archivos:

find . -type f -exec grep -En '.{12}' {} +

Algunas grepimplementaciones como GNU grep, pueden hacer la búsqueda de archivos ellos mismos.

grep -rEn '.{12}' .

Pero tenga cuidado con los enlaces simbólicos y otros archivos no regulares.


Me gusta esto porque es simple, y esperaba hacer algo como esto (todavía no lo he logrado).
Marcin

12

Solución AWK

awk '{       
if (length($0) > 5)
        print $0;'} yourfile

O, más concisamente:

awk 'length > 5' file

99
Podemos acortar su versiónawk 'length > 5'
Cuonglm

Gnouc es un asesino de aparatos ortopédicos;)
Ouki

1
+1 paraawk 'length > 5'

3
Con GNU awkel algo menos elegante pero concisoawk '/^.{6,}/'
iruvar

3
@ 1_CR, eso es POSIX y se puede acortar a awk '/.{6}/'(en realidad GNU awk hasta hace poco solía ser aquel en el que eso no funcionaría a menos que pase POSIXLY_CORRECT a su entorno).
Stéphane Chazelas

5

Como lo único que faltaba era una sedsolución

sed -n '/^.\{6,\}/p' file

5

Solución bash

#!/bin/bash

count=0

while read; do
    ((++count)) 
    len=${#REPLY}
    if ((len > 80)); then
        echo "Line $count is $len characters."
    fi
done

Así, por ejemplo, ./whatever.sh < input.file. Esto no incluye la nueva línea restando 1 de $len; Si eso no es deseable, o si su entrada utiliza terminaciones CRLF, debe ajustar en consecuencia.


1
¿Por qué no ${#line}evitar el exprtenedor?
iruvar

1
ja ja, +1 para la bashsolución pura . Pero tenga en cuenta que a menos que se quede IFS=delante read, se ignorarán los espacios iniciales.
iruvar

1
Agregado en algunas buenas prácticas bash. También tenga en cuenta que la nueva línea no se toma en cuenta, $linepor lo que no es necesario restar una.
iruvar

2
@ 1_CR en realidad si no le da readun nombre para leer, leerá REPLYe incluirá todos los espacios en blanco. No IFSse necesita configuración.
kojiro

2
Eso va a ser extremadamente lento y maneja especialmente los caracteres de barra invertida. while readlos bucles para procesar texto son realmente una mala práctica.
Stéphane Chazelas

4

Con perl(por ejemplo), suponiendo que está buscando líneas de más de 80 caracteres:

Para mostrar las líneas:

$ perl -nle 'print if length > 80' your_file

Para mostrar el número de líneas:

$ perl -nle 'print "$.\n" if length > 80' your_file

O ambos:

$ perl -nle 'print "[$.]:  $_\n" if length > 80' your_file

3
Debe agregar la -llínea de comando, perlcontará el salto de línea en sus líneas.
Cuonglm

1

Rubí:

ruby -lne 'puts $_ if $_.size > 5' intputfile

Python:

python -c "import sys;[ sys.stdout.write(''.join(line)) for line in sys.stdin if len(line.strip()) > 5 ]" < inputfile

1

Aquí hay otra solución bash (bash 4):

minlen=5 # minimum length of a line
mapfile -tO1 < inputfile # Map the file to the array MAPFILE (by default)
                         # Start the array at index 1
for i in "${!MAPFILE[@]}"; do
  (( ${#MAPFILE[i]} > minlen )) || unset MAPFILE[i] # Remove shorter elements
done

La matriz resultante es escasa, por lo que se mantienen los índices de la matriz. Desde que comenzamos en 1, los índices son los números de línea de las líneas que guardamos. Podemos generar solo esos números de línea:

printf 'Long lines found at: '
printf '%d, ' "${!MAPFILE[@]}"
echo

O podemos generar las líneas en sí mismas:

printf '%s\n' "${MAPFILE[@]}"
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.