Tengo un archivo que contiene aproximadamente 10 millones de líneas.
Quiero eliminar todas las líneas del archivo que tengan menos de seis caracteres.
¿Cómo hago esto?
command-line
text-processing
Dime por qué
fuente
fuente
Respuestas:
Hay muchas maneras de hacer esto.
Utilizando
grep
:Ahora
out.txt
contendrá líneas que tienen seis o más caracteres.Manera inversa:
Usando
sed
, eliminando líneas de longitud 5 o menos:Forma inversa, líneas de impresión de longitud seis o más:
Puede guardar la salida en un archivo diferente usando el
>
operador comogrep
o editar el archivo en el lugar usando la-i
opción desed
:Se realizará una copia de seguridad del archivo original
file.txt.bak
y se modificará el archivo modificadofile.txt
.Si no desea mantener una copia de seguridad:
Usando shell, más lento, no hagas esto , esto es solo para mostrar otro método:
Utilizando
python
, incluso más lento quegrep
,sed
:Mejor usar la comprensión de la lista para ser más Pythonic:
fuente
Es muy simple:
Esto es extremadamente eficiente, ya
grep
que no intentará analizar más de lo que necesita, ni interpretará los caracteres de ninguna manera: simplemente envía una línea (completa) a stdout (que el shell luego redirige al archivo de resultados) tan pronto como vio 6 caracteres en esa línea (.
en un contexto regexp coincide con cualquier 1 carácter).Por lo tanto, grep solo generará líneas que tengan 6 (o más) caracteres, y las otras no se generarán por grep, por lo que no se convertirán en archivos de resultados.
fuente
Solución # 1: usando C
La forma más rápida: compila y ejecuta este programa en C:
Compile con
gcc program.c -o program
, ejecute con./program file line_length
(wherefile
= ruta al archivo yline_length
= longitud mínima de línea, en su caso6
; la longitud máxima de línea está limitada a1000000
caracteres por línea; puede cambiar esto cambiando el valor deMAX_BUFFER_SIZE
).(Truco para sustituir
\n
con\0
encontrado aquí .)Comparación con todas las otras soluciones propuestas para esta pregunta, excepto la solución de shell (prueba ejecutada en un archivo de ~ 91MB con 10M líneas con una longitud promedio de 8 caracteres):
Solución # 2: usando AWK:
length>=6
: silength>=6
devuelve VERDADERO, imprime el registro actual.Solución # 3: usando Perl:
lenght>=6
devuelve VERDADERO, imprime el registro actual.fuente
awk
solución ...sed
solución (sucede, lo sé). XDpos
variable? Entiendo que devuelve un puntero al personajeline
con un carácter de nueva línea, pero parece que nunca lo usas. Y si no lo encuentra, simplemente configúrelo igual a\0
.\0
(strchr()
devuelve un puntero NULL si no se encuentra el carácter). El punto es reemplazar cada nueva línea al final de cada línea\0
para que la nueva línea nunca se cuente porstrlen()
: esto es para que la longitud siempre se pueda comparar con 6, independientemente de una posible nueva línea faltante en la última línea. Tratar de manera diferente solo la última línea sería mucho más eficiente, lo sé. Probablemente actualizaré esto más tarde.grep
solución en el mismo archivo y en realidad es más rápido (probablemente porquestrlen()
no es la mejor idea aquí) . Intentaré usar ungetchar()
bucle para verificar solo el primer carácter N, supongo que eso debería mejorarlo visiblemente. Y sí, cualquier línea sobre la longitud del búfer simplemente se corta a la longitud del búfer.Puede usar Vim en modo Ex:
\v
enciende la magia.{6}
encontrar líneas con 6 o más caracteresv
invertir selecciónd
Eliminarx
guardar y cerrarfuente
Solución de rubí:
Idea simple: redirija el archivo al stdin de ruby e imprima la línea desde el stdin solo si su longitud es mayor o igual a 6
fuente