Многократный поиск и замена действий в одном большом текстовом файле

11

У меня большой текстовый файл (около 2 ГБ). Я хочу выполнить пять операций поиска и замены одного и того же файла и хотел бы сделать это одной командой. Обычно я использую vim, открываю файл, выполняю одно действие замены, затем следующее и т. Д. Есть одна ловушка, поскольку я заметил, что после трех или четырех поисков vim падает из-за проблем с памятью.

Вот два примера команды, которую я использую в Vim:

:%s/www\.abcdef/www.test.abcdef/g 
:%s/www\.klmnop/www.test.klmnop/g

Каков наилучший способ справиться с этим?

SPRBRN
источник

Ответы:

8

Я бы использовал sed, как это:

sed -i "s/www\.abcdef/www.test.abcdef/g;s/www\.kmlnop/www.test.klmnop/g;" yourfile.txt

-iопция означает замену на месте. Вы можете указать sed создать резервную копию вашего файла с расширением этой опции ( -i.bakсоздаст резервную копию yourfile.txt как yourfile.txt.bak).

ssssteffff
источник
Это быстро! Не только ваш ответ ;-), но этот скрипт с 5 поисками и заменами примерно в 10 раз быстрее, чем просто открытие файла в vim. Одна вещь смутила меня, хотя. Сначала я думал, что файл .bak будет отредактированным, но, конечно, оригинал.
СПРБРН
Десять операций поиска и замены (с тысячами обращений) в файле объемом 2 ГБ за один раз, без проблем с памятью. Менее двух минут на среднем рабочем столе - супер!
СПРБРН
Один вопрос ... Вы избегаете точек в строке замены. Это необходимо?
СПРБР
1
Добро пожаловать @rxt :) На самом деле, вы правы, вы можете использовать неэкранированные точки в строке замены в sed. Я пытался, и это работает. В Unix & Linux Stackexchange есть хорошая нить , и в принятом ответе не упоминаются точки в качестве символов для выхода.
ssssteffff
2
@rxt вы сказали заменить строку, извините, нет вам не нужно избегать их там.
тердон
6

Если у вас есть еще много шаблонов поиска, вы можете сохранить их в файле и прочитать оттуда замены. Например, скажем, что это содержимое replacements.txt:

www\.abcdef www.test.abcdef 
www\.klmnop www.test.klmnop

Затем вы можете прочитать список N замен и заменить их следующим:

while read from to; do
  sed -i "s/$from/$to/" infile.txt ; 
done < replacements.txt 

НОТЫ:

  • Это предполагает, что ваши строки поиска не содержат пробелов и любые странные символы должны быть экранированы replacements.txt.
  • Он будет запускаться по одному sedна замену, что может занять некоторое время, если у вас много операций замены.
  • Он может иметь дело с произвольным числом замен (тысячи или миллионы или что-то еще), если вы не возражаете, что это займет немного больше времени.

Другим вариантом будет написать выше в виде sedсценария:

s/www\.abcdef/www\.test\.abcdef/g;
s/www\.kmlnop/www\.test\.klmnop/g;
s/aaaa/bbbb/g;
s/cccc/dddd/g;
s/eeee/ffff/g;

Затем вы можете запустить скрипт для вашего файла, и он сделает все замены за один раз:

sed -f replace.sed infile.txt 
terdon
источник
+1 для ,, другой вариант ''. Может быть удобно хранить замены в файле! (Надеюсь, я это запомню ...)
mpy
+1 для «другого варианта» также потому, что он использует нативную функциональность, а не собственный сценарий, поэтому он более переносимый / совместный
Дэвид Кук
@DavidCook спасибо, но он не более родной или переносной, чем другие. Первый подход заключается в использовании цикла оболочки POSIX, он так же переносим, ​​как и второй. Это будет намного медленнее, поскольку он использует цикл оболочки.
Тердон
Вы правы, я имел в виду, что формат файла сценария sed является более переносимым, поскольку он использует встроенную функциональность sed, а не сценарий, который должен использоваться совместно с файлом replacements.txt. Тем не менее, они оба отличные варианты!
Дэвид Кук