it-swarm.com.de

Wie entferne ich alle Zeilen in einer Datei, die weniger als 6 Zeichen enthalten?

Ich habe eine Datei mit ungefähr 10 Millionen Zeilen.

Ich möchte alle Zeilen in der Datei entfernen, die weniger als sechs Zeichen enthalten.

Wie mache ich das?

17
TellMeWhy

Dafür gibt es viele Möglichkeiten.

grep verwenden:

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

Jetzt enthält out.txt Zeilen mit sechs oder mehr Zeichen.

Umgekehrter Weg:

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

Mit sed Zeilen mit einer Länge von 5 oder weniger entfernen:

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

In umgekehrter Reihenfolge werden Zeilen mit einer Länge von sechs oder mehr gedruckt:

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

Sie können die Ausgabe mit dem Operator > wie grep in einer anderen Datei speichern oder die Datei direkt mit der Option -i von sed bearbeiten:

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

Die Originaldatei wird als file.txt.bak und die geänderte Datei als file.txt gesichert.

Wenn Sie keine Sicherungskopie erstellen möchten:

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

Verwenden Sie Shell, langsamer, machen Sie das nicht, um eine andere Methode zu zeigen:

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

Mit python, sogar langsamer als 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')

Verwenden Sie das Listenverständnis besser, um pythonischer zu sein:

#!/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')
30
heemayl

Es ist sehr einfach:

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

Dies ist äußerst effizient, da grep nicht versucht, mehr als nötig zu analysieren oder die Zeichen in irgendeiner Weise zu interpretieren: Es wird einfach eine (vollständige) Zeile an stdout gesendet (die die Shell dann an resultfile weiterleitet). sobald 6 Zeichen in dieser Zeile (. in einem regulären Kontext entspricht einem beliebigen Zeichen).

Grep gibt also nur Zeilen mit 6 (oder mehr) Zeichen aus, und die anderen werden nicht von grep ausgegeben, damit sie nicht in die Ergebnisdatei gelangen.

19
Olivier Dulac

Lösung 1: Verwenden von C

Schnellster Weg: Kompilieren und starten Sie dieses C-Programm:

#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 = '\0';
            if(strlen(line) >= length)
                printf("%s\n", line);
        }

        fclose(file);
    }
    else {
        perror(argv[1]);
        return 1;
    }

    return 0;
}

Kompilieren Sie mit gcc program.c -o program, führen Sie mit ./program file line_length aus (wobei file = Pfad zur Datei und line_length = minimale Zeilenlänge, in Ihrem Fall 6; die maximale Zeile Die Länge ist auf 1000000 Zeichen pro Zeile begrenzt. Sie können dies ändern, indem Sie den Wert von MAX_BUFFER_SIZE) ändern.

(Trick, um \n durch \0 zu ersetzen found here .)

Vergleich mit allen anderen Lösungen, die für diese Frage vorgeschlagen wurden, mit Ausnahme der Shell-Lösung (Testlauf mit einer ~ 91-MB-Datei mit 10-MB-Zeilen und einer durchschnittlichen Länge von 8 Zeichen):

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

Lösung 2: Verwenden von AWK:

awk 'length>=6' file
  • length>=6: Wenn length>=6 TRUE zurückgibt, wird der aktuelle Datensatz gedruckt.

Lösung 3: Verwenden von Perl:

Perl -lne 'length>=6&&print' file
  • Wenn lenght>=6 TRUE zurückgibt, wird der aktuelle Datensatz gedruckt.

% 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
14
kos

Sie können Vim im Ex-Modus verwenden:

ex -sc 'v/\v.{6}/d' -cx file
  1. \v Magie einschalten

  2. .{6} findet Zeilen mit 6 oder mehr Zeichen

  3. v Auswahl umkehren

  4. d löschen

  5. x speichern und schließen

2
Steven Penny

Ruby-Lösung:

$ cat input.txt                                                                                                          
abcdef
abc
abcdefghijk

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

Einfache Idee: Leiten Sie die Datei in Rubys Standard um und drucken Sie die Zeile nur dann aus dem Standard, wenn die Länge größer oder gleich 6 ist

1