Come rimuovere tutte le righe in un file con meno di 6 caratteri?

17

Ho un file contenente circa 10 milioni di righe.

Voglio rimuovere tutte le righe nel file con meno di sei caratteri.

Come faccio a fare questo?

    
posta TellMeWhy 27.01.2016 - 13:15

5 risposte

31

Ci sono molti modi per farlo.

Uso di grep :

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

Ora out.txt conterrà linee con sei o più caratteri.

Modo inverso:

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

Utilizzo di sed , rimozione di righe di lunghezza pari o inferiore a 5:

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

Modo inverso, stampa di righe di lunghezza pari o superiore a sei:

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

Puoi salvare l'output in un file diverso usando > operatore come grep o modifica il file sul posto usando -i opzione di sed :

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

Il file originale verrà sottoposto a backup in file.txt.bak e il file modificato sarà file.txt .

Se non desideri conservare un backup:

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

Usando la shell, Più lento, Non farlo , questo è solo per mostrare un altro metodo:

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

Uso di python , anche più lento di 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')

Utilizzare meglio la comprensione delle liste per essere più 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')
    
risposta data heemayl 27.01.2016 - 13:20
20

È molto semplice:

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

Questo è estremamente efficiente, poichè grep non proverà ad analizzare più del necessario, né a interpretare i caratteri in alcun modo: semplicemente invierà una riga (intera) a stdout (che la shell quindi reindirizzerà a resultfile) non appena ha visto 6 caratteri su quella riga ( . in un contesto regexp corrisponde a qualsiasi carattere 1).

Quindi grep emetterà solo linee con 6 (o più) caratteri, e gli altri non verranno emessi da grep in modo che non possano farlo in resultfile.

    
risposta data Olivier Dulac 27.01.2016 - 18:59
15

Soluzione n. 1: utilizzando C

Il modo più veloce: compilare ed eseguire questo programma 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; }

Compilare con gcc program.c -o program , eseguire con ./program file line_length (dove file = percorso del file e line_length = lunghezza minima della linea, nel tuo caso 6 ; la lunghezza massima della linea è limitata a 1000000 caratteri per riga; puoi modificarlo modificando il valore di MAX_BUFFER_SIZE ).

(Trucco per sostituire \n con length>=6 trovato qui .)

Confronto con tutte le altre soluzioni proposte a questa domanda tranne la soluzione di shell (test eseguito su un file ~ 91MB con linee 10M con una lunghezza media di 8 caratteri):

awk 'length>=6' file

Soluzione n. 2: utilizzo di AWK:

perl -lne 'length>=6&&print' file
  • length>=6 : se lenght>=6 restituisce TRUE, stampa il record corrente.

Soluzione n. 3: utilizzando 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% restituisce TRUE, stampa il record corrente.
#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; }
    
risposta data kos 27.01.2016 - 13:34
2

Puoi usare Vim in modalità Ex:

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

  2. .{6} trova le linee con 6 o più caratteri

  3. v inverti selezione

  4. d elimina

  5. x salva e chiudi

risposta data Steven Penny 16.04.2016 - 21:03
1

Soluzione di Ruby:

$ cat input.txt                                                                                                          
abcdef
abc
abcdefghijk

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

Semplice idea: reindirizza il file nello stdin di ruby e stampa la riga da stdin solo se è maggiore o uguale a 6

    
risposta data Sergiy Kolodyazhnyy 07.01.2017 - 09:57

Leggi altre domande sui tag