Замена огромных блоков на седь - PullRequest
0 голосов
/ 01 сентября 2009

У меня есть 2 файла, которые создаются в другом месте. Первый - «что искать», а второй - замена. Оба файла огромные, около 2-3 МБ каждый.

Мне нужно написать bash-скрипт, который берет еще больший файл (около 200-300 МБ) и заменяет все вхождения содержимого file1 на содержимое file2.

Проблема в том, что file1 и file2 могут содержать любые возможные символы, включая специальные символы регулярного выражения.

Как мне решить эту проблему с помощью sed?

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 01 сентября 2009

Поскольку на самом деле вам не нужны регулярные выражения, просто прямое сопоставление строк, sed излишне. Что вам действительно нужно, так это потоковый редактор с фиксированной строкой (может быть, даже двоичный). К сожалению, я не знаю ни одного ... Я не хочу предлагать, возможно, заново изобрести колесо, но вы могли бы довольно быстро написать что-то в C, что бы делать то, что вы хотите. Черновой набросок:

  • чтение файла поиска в память
  • создать буфер того же размера, что и search-file
  • чтение из стандартного ввода (или входного файла) в буфер.
    • Для каждого символа, если он не соответствует параллельному символу из файла поиска, сдвиньте буфер. Чтобы узнать, на какую величину его сдвинуть, читайте, пока не найдете соответствие первому символу входного файла, затем проверьте, совпадают ли остальные, повторяя, пока не найдете частичное совпадение с входным файлом (или не получили до конца буфера). При перемещении выведите все несовпадающие символы в стандартный вывод (или файл вывода)
    • Если буфер заполняется, то есть полностью совпадает с входным файлом, выведите файл замены в стандартный вывод (или выходной файл). В зависимости от скорости памяти и скорости вы можете хранить файл-замену в памяти или каждый раз читать его с диска.

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

sed -e 's/\\/\\\\/g' -e 's@/@\/@' -e 's/\[/\\[/g' ...

(сначала убедитесь, что вы сделали \)

1 голос
/ 03 сентября 2009

Может быть, посмотрите на chgrep:

http://www.bmk -it.com / проекты / chgrep /

Приветствия

gregx

0 голосов
/ 01 сентября 2009

Я не знаю, что такое sed, но в Perl вы могли бы сделать это (не проверяя мою голову):

perl -0777 -pe 'BEGIN{local $/ = undef; open FROM, "<", shift @ARGV; $from = <FROM>; open TO, "<" shift @ARGV; $to = <TO>} s/\Q$from\E/$to/sog' file1 file2 bigger-file > new-bigger-file

Если вам интересно попробовать Perl, я могу попробовать его для вас завтра.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...