Como removo todas as linhas de um arquivo com menos de 6 caracteres?

17

Eu tenho um arquivo contendo aproximadamente 10 milhões de linhas.

Eu quero remover todas as linhas do arquivo com menos de seis caracteres.

Como faço isso?

    
por TellMeWhy 27.01.2016 / 13:15

5 respostas

30

Existem muitas maneiras de fazer isso.

Usando grep :

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

Agora, out.txt conterá linhas com seis ou mais caracteres.

Caminho reverso:

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

Usando sed , removendo linhas de comprimento igual ou inferior a 5:

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

Reverse, imprimindo linhas com seis ou mais comprimentos:

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

Você pode salvar a saída em um arquivo diferente usando o operador > como grep ou editar o arquivo no local usando a opção -i de sed :

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

Será feito o backup do arquivo original como file.txt.bak e o arquivo modificado será file.txt .

Se você não quiser manter um backup:

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

Usando o shell, Mais lento, não faça isso , isso é apenas para mostrar outro método:

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

Usando python , ainda mais 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')

Melhor usar a compreensão da lista para ser mais 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')
    
por heemayl 27.01.2016 / 13:20
19

É muito simples:

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

Isto é extremamente eficiente, pois grep não tentará analisar mais do que precisa, nem interpretar os caracteres de qualquer forma: ele simplesmente envia uma linha (inteira) para stdout (que o shell então redireciona para o arquivo de resultado) assim que ele viu 6 caracteres nessa linha ( . em um contexto regexp corresponde a qualquer caractere 1).

Assim, o grep só irá mostrar as linhas com 6 (ou mais) caracteres, e os outros não serão gerados pelo grep, para que eles não passem para o resultado.

    
por Olivier Dulac 27.01.2016 / 18:59
14

Solução # 1: usando C

Caminho mais rápido: compile e execute este programa em 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 com gcc program.c -o program , executado com ./program file line_length (onde file = caminho para o arquivo e line_length = tamanho mínimo da linha, no seu caso 6 ; o tamanho máximo da linha é limitado a 1000000 caracteres por linha; você pode mudar isso alterando o valor de MAX_BUFFER_SIZE ).

(Truque para substituir \n por length>=6 encontrado aqui .)

Comparação com todas as outras soluções propostas para esta questão, exceto a solução shell (teste executado em um arquivo ~ 91MB com 10M linhas com um comprimento médio de 8 caracteres):

awk 'length>=6' file

Solução # 2: usando o AWK:

perl -lne 'length>=6&&print' file
  • length>=6 : se lenght>=6 retornar TRUE, imprime o registro atual.

Solução # 3: usando o 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
  • Se %code% retornar TRUE, imprime o registro atual.
#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; }
    
por kos 27.01.2016 / 13:34
2

Você pode usar o Vim no modo Ex:

ex -sc 'v/\v.{6}/d' -cx file
  1. \v ativam a mágica

  2. .{6} encontra linhas com 6 ou mais caracteres

  3. v inverter seleção

  4. d delete

  5. x salvar e fechar

por Steven Penny 16.04.2016 / 21:03
1

Solução Ruby:

$ cat input.txt                                                                                                          
abcdef
abc
abcdefghijk

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

Idéia simples: redirecionar o arquivo para o stdin do ruby e imprimir a linha do stdin somente se ele for maior ou igual a 6

    
por Sergiy Kolodyazhnyy 07.01.2017 / 09:57