Как я удаляю все строки в файле, которые являются меньше чем 6 символами?

У меня есть файл, содержащий приблизительно 10 миллионов строк.

Я хочу удалить все строки в файле, которые являются меньше чем шестью символами.

Как я делаю это?

17
задан 27 January 2016 в 05:48

5 ответов

Существует много способов сделать это.

Используя grep:

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

Теперь out.txt будет содержать строки, имеющие шесть или больше символов.

Обратный путь:

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

Используя sed, удаление строк длины 5 или меньше:

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

Обратный путь, печатая строки длины шесть или больше:

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

Можно сохранить вывод в другом использовании файла > оператор как grep или отредактируйте файл оперативное использование -i опция sed:

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

Исходный файл будет сохранен как file.txt.bak и измененный файл будет file.txt.

Если Вы не хотите сохранять резервное копирование:

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

Используя оболочку, Медленнее, не делайте этого, это только ради показа другого метода:

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

Используя python, еще медленнее, чем 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')

Лучше используйте понимание списка, чтобы быть большим количеством 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')
30
ответ дан 23 November 2019 в 02:16

Это очень просто:

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

Это чрезвычайно эффективно, поскольку grep не попытается проанализировать больше, чем этому нужно, ни интерпретировать символы всегда: это просто отправляет (целую) строку в stdout (который оболочка затем перенаправляет к resultfile) , как только это видело, 6 символов на той строке (. в regexp контексте соответствует любому 1 символу).

, Таким образом, grep только произведет строки, имеющие 6 (или больше) символы, и другие не производятся grep, таким образом, они не добираются до resultfile.

19
ответ дан 23 November 2019 в 02:16

Можно использовать Vim в режиме Ex:

ex -sc 'v/\v.{6}/d' -cx file
  1. \v включают волшебство

  2. .{6}, находят строки с 6 или больше символами

  3. v, выбор инвертирования

  4. d удаляет

  5. x, сохраняют и закрываются

2
ответ дан 23 November 2019 в 02:16

Решение № 1: использование C

Самый быстрый путь: скомпилируйте и запустите эту программу 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 = '\0';
            if(strlen(line) >= length)
                printf("%s\n", line);
        }

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

    return 0;
}

Скомпилируйте с gcc program.c -o program, выполненный с ./program file line_length (где file = соедините каналом в файл и line_length = минимальная длина строки, в Вашем случае 6; максимальная длина строки ограничена 1000000 символы на строку; можно изменить это путем изменения значения MAX_BUFFER_SIZE).

(Прием для замены \n с \0 найденный здесь.)

Сравнение со всеми другими решениями, предложенными этому вопросу кроме решения для оболочки (тестовый прогон на ~91MB файле с 10M строки со средней длиной 8 символов):

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

Решение № 2: использование AWK:

awk 'length>=6' file
  • length>=6: если length>=6 возвраты ПРАВДА, печатает текущую запись.

Решение № 3: использование Perl:

perl -lne 'length>=6&&print' file
  • Если lenght>=6 возвраты ПРАВДА, печатает текущую запись.

% 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
ответ дан 23 November 2019 в 02:16

Решение Ruby:

$ cat input.txt                                                                                                          
abcdef
abc
abcdefghijk

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

Простая идея: файл перенаправления в stdin рубина и строка печати от stdin, только если это - длина, больше или равная 6

1
ответ дан 23 November 2019 в 02:16

Другие вопросы по тегам:

Похожие вопросы: