У меня есть файл, содержащий около 10 миллионов строк.
Я хочу удалить все строки в файле длиной менее шести символов.
Как мне это сделать?
command-line
text-processing
Скажи мне почему
источник
источник
Ответы:
Есть много способов сделать это.
Использование
grep
:Теперь
out.txt
будет содержать строки, имеющие шесть или более символов.Обратный путь:
Используя
sed
, удаляя строки длиной 5 или меньше:Обратный путь, печать строк длиной шесть и более:
Вы можете сохранить вывод в другом файле, используя
>
оператор какgrep
или отредактировать файл на месте, используя-i
параметрsed
:Резервное копирование исходного файла будет выполнено так же, как
file.txt.bak
и измененный файлfile.txt
.Если вы не хотите хранить резервную копию:
Используя shell, Slower, не делайте этого , это просто для того, чтобы показать другой метод:
Использование
python
даже медленнее , чемgrep
,sed
:Лучше использовать понимание списка, чтобы быть более Pythonic:
источник
Это очень просто:
Это чрезвычайно эффективно, так как
grep
не будет пытаться ни анализировать больше, чем нужно, ни каким-либо образом интерпретировать символы: он просто отправляет (целую) строку в stdout (который оболочка затем перенаправляет в файл результатов), как только увидит 6 символы в этой строке (.
в контексте регулярного выражения соответствует любому 1 символу).Таким образом, grep будет выводить только строки с 6 (или более) символами, а остальные не выводятся с помощью grep, поэтому они не преобразуются в файл результата.
источник
Решение № 1: использование C
Самый быстрый способ: скомпилировать и запустить эту программу на C:
Скомпилируйте с
gcc program.c -o program
, запустите с./program file line_length
(гдеfile
= путь к файлу иline_length
= минимальная длина строки, в вашем случае6
; максимальная длина строки ограничена1000000
символами в строке; вы можете изменить это, изменив значениеMAX_BUFFER_SIZE
).(Trick для замены
\n
с\0
найден здесь .)Сравнение со всеми другими решениями, предложенными для этого вопроса, за исключением решения оболочки (тестовый запуск файла ~ 91 МБ с 10M строками со средней длиной 8 символов):
Решение № 2: использование AWK:
length>=6
: еслиlength>=6
возвращает TRUE, печатает текущую запись.Решение № 3: использование Perl:
lenght>=6
возвращает TRUE, печатает текущую запись.источник
awk
решения ..sed
решение (такое бывает, я знаю). XDpos
переменной? Я получаю, он возвращает указатель на символline
с символом новой строки, но вы, кажется, никогда не используете его. И если вы не найдете его, вы просто установите его равным\0
.\0
(strchr()
возвращает нулевой указатель, если символ не найден). Точка заменяет каждую новую строку в конце каждой строки\0
так, чтобы новая строка никогда не подсчитываласьstrlen()
: это так, что длину всегда можно сравнить с 6, независимо от потенциального отсутствия новой строки в последней строке. Я знаю, что по-другому рассматривать только последнюю строку было бы гораздо эффективнее. Я, вероятно, обновлю это позже.grep
решение на том же файле, и оно на самом деле быстрее (вероятно, потому чтоstrlen()
здесь не самая лучшая идея) , Я попытаюсь использоватьgetchar()
цикл для проверки только первого символа N, я думаю, это должно заметно улучшить его. И да, любая линия по длине буфера просто обрезается до длины буфера.Вы можете использовать Vim в режиме Ex:
\v
включить магию.{6}
найти строки с 6 или более символамиv
наоборотd
удалятьx
сохранить и закрытьисточник
Рубиновое решение:
Простая идея: перенаправить файл в стандартный ruby и выводить строку из стандартного stdin, только если его длина больше или равна 6
источник