Как удалить все строки в файле размером менее 6 символов?

17

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

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

Как это сделать?

    
задан TellMeWhy 27.01.2016 в 12:15
источник

5 ответов

31

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

Использование 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')
    
ответ дан heemayl 27.01.2016 в 12:20
источник
20

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

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

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

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

    
ответ дан Olivier Dulac 27.01.2016 в 17:59
15

Решение № 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 = '
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; }

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

(Trick для замены \n с length>=6 найдено здесь .)

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

awk 'length>=6' file

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

perl -lne 'length>=6&&print' file
  • length>=6 : если lenght>=6 возвращает TRUE, печатает текущую запись.

Решение №3: использование 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
  • Если %co_de% возвращает TRUE, печатает текущую запись.
%pr_e%     
ответ дан kos 27.01.2016 в 12:34
2

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

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

  2. .{6} найти строки с 6 или более символами

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

  4. d delete

  5. x сохранить и закрыть

ответ дан Steven Penny 16.04.2016 в 19:03
1

Решение Ruby:

$ cat input.txt                                                                                                          
abcdef
abc
abcdefghijk

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

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

    
ответ дан Sergiy Kolodyazhnyy 07.01.2017 в 08:57