Быстро заменить текст в очень большой файл


25

У меня есть текстовый файл 25 ГБ, который нуждается в замене строки только на несколько строк. Я могу sedуспешно использовать, но это занимает очень много времени для запуска.

sed -i 's|old text|new text|g' gigantic_file.sql

Есть ли более быстрый способ сделать это?


Знаете ли вы номера строк, где находится текст для замены? Если не единственный способ ускорить его, это получить более быстрый компьютер. Тот факт, что у вас большой объем данных, означает, что для их поиска потребуется много времени.
Дэвид Кинг

Я могу быстро найти номера строк, так что да.
eisaacson

Вы также можете использовать несколько процессорных ядер, чтобы ускорить его - rankfocus.com/use-cpu-cores-linux-commands
ahaswer

Не используйте sed для больших файлов. Взгляните на vi или vim .
MikeJRamsey56

Ответы:


26

Можешь попробовать:

sed -i '/old text/ s//new text/g' gigantic_file.sql

Из этой ссылки :

ОПТИМИЗАЦИЯ СКОРОСТИ: Если необходимо увеличить скорость выполнения (из-за больших входных файлов или медленных процессоров или жестких дисков), подстановка будет выполняться быстрее, если перед выражением "s /.../ передается выражение" find ". ../ "инструкция.

Вот сравнение с файлом 10G. До:

$ time sed -i 's/original/ketan/g' wiki10gb
real    5m14.823s
user    1m42.732s
sys     1m51.123s

После:

$ time sed -i '/ketan/ s//original/g' wiki10gb
real    4m33.141s
user    1m20.940s
sys     1m44.451s

Последний с sedошибкой. Я вчера редактировал этот пост, чтобы исправить последнюю sedкоманду, которая должна быть, time sed -i '/original/ s//ketan/g' wiki10gbа не time sed -i '/ketan/ s//original/g' wiki10gb. Сегодня я возвращаю свое редактирование, потому что: 1. времена больше не соответствуют команде и 2. я провел тот же тест с GNU sed для файла размером 3+ ГБ и не вижу никакой разницы между этими двумя sedальтернативами. Я подозреваю, что разница во времени связана с ошибкой.
Ксиенн

@ xhienne Я не уверен, что ты имеешь в виду под орфографической ошибкой. В первом цикле я заменяю слово «оригинал» на «кетан», а во втором я заменяю термин «кетан» термином «оригинал», что приводит к одинаковому количеству замен в любом случае.
MKC

1
Я применял исправление, о котором сообщил новый пользователь с недостаточной репутацией. Теперь я понимаю, что ты сделал. Однако, если вы хотите доказать, что один синтаксис лучше, чем другой, вы должны выполнить точно такую ​​же операцию, что здесь не так (в отношении ЦП поиск строки из 5 символов не совпадает с поиском 7-символьная строка). Более того, этот вид теста для файла объемом 10 ГБ сильно зависит от нагрузки на ваш компьютер (процессор, диск). Я timeлично видел много колебаний в результатах, но в целом разницы во времени не было.
xhienne

Я считаю, что это связано - см. Принятый ответ здесь, stackoverflow.com/questions/11145270/… >> sed передает весь файл, но, как отмечено в этом ответе, указание номера строки (если известно) помогает: в моем случае увеличение скорости выполнения в ~ 2 раза (GNU sed 4.5). Вы можете grep -n или ripgrep (rg), чтобы найти номера строк, основываясь на поиске по шаблону. По сути, указание номера строки похоже на наличие результата поиска в этом файле согласно ответу выше.
Виктория Стюарт

1

Короткий ответ - «Нет» - ваш ограничивающий фактор для такого рода операций - дисковый ввод-вывод. Нет возможности потоковой передачи 25 ГБ диска быстрее. Вы можете получить небольшое улучшение, если вы не редактируете на месте, и вы записываете результат на sedотдельный диск (если у вас есть один доступный) - потому что таким образом вы можете читать с одного, в то время как запись на другой, и есть немного меньше разногласий в результате.

Вы могли бы немного ускорить его, не используя движок регулярных выражений для каждой строки - например, с помощью perl (я уверен, что вы можете сделать это с sedпомощью синтаксиса, но я не знаю) - это начнется с линия 10 000 и далее.

perl -pe '$. > 10_000 && s/old_text/new_text/g' 

И если есть какие-либо сложности в RE (метасимволы), то их минимизация немного повысит эффективность движка регулярных выражений.


1
В sed -i '10000,$ s/old_text/new_text/g'
седе

Прекрасный. Я не знаю, как sedсравнивать - я полагаю, немного быстрее, но не сильно из-за размера файла.
Sobrique

Я бы предположил, что Perl быстрее, чем Sed, но Sed немного менее загадочно, или, скорее, требует меньше начальной кривой обучения.
Dani_l

1
Смотрите, сейчас я бы сказал наоборот - вы можете (почти) записи sedв perl, но последний также позволяет писать более многословным скрипты тоже.
Sobrique

0

Если новый и старый тексты имеют одинаковую длину, вы можете искать в файле и записывать только измененные байты вместо копирования всего файла. В противном случае вы попадаете в ловушку большого количества данных.

Примечание: это сложно и требует написания собственного кода.

См. Справочную страницу для fseek, если вы работаете в C или C ++, или ваши любимые языковые оболочки для системных вызовов поиска и записи.

Если вы настаиваете на использовании только командной строки и можете получить байтовые смещения текста, вы можете написать заменяющий текст на месте с помощью тщательно написанных команд «dd».

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.