¿Cómo elimino todas las líneas de un archivo que tienen menos de 6 caracteres?

17

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?

    
pregunta TellMeWhy 27.01.2016 - 12:15

5 respuestas

31

Hay muchas maneras de hacer esto.

Utilizando grep :

grep -E '^.{6,}$' file.txt >out.txt

Ahora out.txt contendrá líneas con seis o más caracteres.

Camino inverso:

grep -vE '^.{,5}$' file.txt >out.txt

Utilizando sed , eliminando líneas de longitud 5 o menos:

sed -r '/^.{,5}$/d' file.txt

Modo inverso, imprimiendo líneas de longitud seis o más:

sed -nr '/^.{6,}$/p' file.txt 

Puede guardar la salida en un archivo diferente utilizando el operador > como grep o editar el archivo in situ utilizando la opción -i de sed :

sed -ri.bak '/^.{6,}$/' file.txt 

Se realizará una copia de seguridad del archivo original como file.txt.bak y el archivo modificado será file.txt .

Si no desea mantener una copia de seguridad:

sed -ri '/^.{6,}$/' file.txt

Usando shell, Más lento, no hagas esto , esto es solo para mostrar otro método:

while IFS= read -r line; do [ "${#line}" -ge 6 ] && echo "$line"; done <file.txt

Utilizando python , incluso más lento que grep , sed :

#!/usr/bin/env python2
with open('file.txt') as f:
    for line in f:
        if len(line.rstrip('\n')) >= 6:
            print line.rstrip('\n')

Mejor uso de la lista de comprensión para ser más Pythonic:

#!/usr/bin/env python2
with open('file.txt') as f:
     strip = str.rstrip
     print '\n'.join([line for line in f if len(strip(line, '\n')) >= 6]).rstrip('\n')
    
respondido por el heemayl 27.01.2016 - 12:20
20

Es muy simple:

grep ...... inputfile > resultfile   #There are 6 dots

Esto es extremadamente eficiente, ya que grep 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 la shell luego redirecciona al archivo de resultados) tan pronto como vio 6 caracteres en esa línea ( . en un contexto de expresión regular coincide con cualquier carácter).

Por lo tanto, grep solo emitirá líneas que tengan 6 (o más) caracteres, y las otras no son generadas por grep, por lo que no llegan al archivo de resultados.

    
respondido por el Olivier Dulac 27.01.2016 - 17:59
15

Solución # 1: usando C

Forma más rápida: compile y ejecute este programa en C:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_BUFFER_SIZE 1000000

int main(int argc, char *argv[]) {
    int length;

    if(argc == 3)
        length = atoi(argv[2]);
    else
        return 1;

    FILE *file = fopen(argv[1], "r");

    if(file != NULL) {
        char line[MAX_BUFFER_SIZE];

        while(fgets(line, sizeof line, file) != NULL) {
            char *pos;

            if((pos = strchr(line, '\n')) != NULL)
                *pos = '
time ./foo file 6

real    0m1.592s
user    0m0.712s
sys 0m0.160s

time grep ...... file

real    0m1.945s
user    0m0.912s
sys 0m0.176s

time grep -E '^.{6,}$'

real    0m2.178s
user    0m1.124s
sys 0m0.152s

time awk 'length>=6' file

real    0m2.261s
user    0m1.228s
sys 0m0.160s

time perl -lne 'length>=6&&print' file

real    0m4.252s
user    0m3.220s
sys 0m0.164s

sed -r '/^.{,5}$/d' file >out

real    0m7.947s
user    0m7.064s
sys 0m0.120s

./script.py >out
real    0m8.154s
user    0m7.184s
sys 0m0.164s
'; if(strlen(line) >= length) printf("%s\n", line); } fclose(file); } else { perror(argv[1]); return 1; } return 0; }

Compile con gcc program.c -o program , ejecute con ./program file line_length (donde file = ruta al archivo y line_length = longitud de línea mínima, en su caso 6 ; la longitud de línea máxima está limitada a 1000000 caracteres por línea; puede cambiar esto cambiando el valor de MAX_BUFFER_SIZE ).

(Truco para sustituir \n con length>=6 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):

awk 'length>=6' file

Solución # 2: usando AWK:

perl -lne 'length>=6&&print' file
  • length>=6 : si lenght>=6 devuelve VERDADERO, imprime el registro actual.

Solución # 3: usando Perl:

% cat file
a
bb
ccc
dddd
eeeee
ffffff
ggggggg
% ./foo file 6
ffffff
ggggggg
% awk 'length>=6' file   
ffffff
ggggggg
% perl -lne 'length>=6&&print' file
ffffff
ggggggg
  • Si %code% devuelve VERDADERO, imprime el registro actual.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_BUFFER_SIZE 1000000

int main(int argc, char *argv[]) {
    int length;

    if(argc == 3)
        length = atoi(argv[2]);
    else
        return 1;

    FILE *file = fopen(argv[1], "r");

    if(file != NULL) {
        char line[MAX_BUFFER_SIZE];

        while(fgets(line, sizeof line, file) != NULL) {
            char *pos;

            if((pos = strchr(line, '\n')) != NULL)
                *pos = '
time ./foo file 6

real    0m1.592s
user    0m0.712s
sys 0m0.160s

time grep ...... file

real    0m1.945s
user    0m0.912s
sys 0m0.176s

time grep -E '^.{6,}$'

real    0m2.178s
user    0m1.124s
sys 0m0.152s

time awk 'length>=6' file

real    0m2.261s
user    0m1.228s
sys 0m0.160s

time perl -lne 'length>=6&&print' file

real    0m4.252s
user    0m3.220s
sys 0m0.164s

sed -r '/^.{,5}$/d' file >out

real    0m7.947s
user    0m7.064s
sys 0m0.120s

./script.py >out
real    0m8.154s
user    0m7.184s
sys 0m0.164s
'; if(strlen(line) >= length) printf("%s\n", line); } fclose(file); } else { perror(argv[1]); return 1; } return 0; }
    
respondido por el kos 27.01.2016 - 12:34
2

Puedes usar Vim en modo Ex:

ex -sc 'v/\v.{6}/d' -cx file
  1. \v activa la magia

  2. .{6} encuentra líneas con 6 o más caracteres

  3. v Invertir selección

  4. d delete

  5. x guardar y cerrar

respondido por el Steven Penny 16.04.2016 - 19:03
1

Solución Ruby:

$ cat input.txt                                                                                                          
abcdef
abc
abcdefghijk

$ ruby -ne 'puts $_ if $_.chomp.length() >= 6 ' < input.txt                                                              
abcdef
abcdefghijk

Idea simple: redirige el archivo a la entrada estándar de ruby e imprime la línea desde la entrada estándar solo si la longitud es mayor o igual a 6

    
respondido por el Sergiy Kolodyazhnyy 07.01.2017 - 08:57

Lea otras preguntas en las etiquetas