Рейтинг:5

Лучший способ удалить текст с начала огромного файла

флаг de

У меня есть огромный файл резервной копии MySQL (из mysqldump) с таблицами в алфавитном порядке. Мое восстановление не удалось, и я хочу продолжить с того места, где остановился, со следующей таблицей в файле резервной копии. (Я исправил проблему, на самом деле это не вопрос восстановления MySQL и т. д.)

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

-- Структура таблицы для `mytable`

Тогда все после этого попадет в мой файл результатов, скажем резервное копирование-secondhalf.sql. Это несколько усложняется тем фактом, что файл сжат bzip2, но это не должно быть слишком большой проблемой.

Я думаю, что я могу сделать это так:

$ bunzip2 -c backup.sql.bz2 | grep --text --byte-offset --only-matching -e '--Структура таблицы для таблицы `mytable`' -m 1

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

$ bunzip2 -c backup.sql.bz2 | dd skip=[число сверху] | bzip2 -c > резервная копия-вторая половина.sql.bz2

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

Есть ли способ сделать это все сразу?

Я не уверен, что мой sed-fu достаточно силен, чтобы выполнить выражение «удалить все строки до регулярного выражения, а затем пропустить остальную часть файла».

Это на Debian Linux, поэтому у меня есть инструменты GNU.

флаг eg
Если строки могут быть произвольной длины, откуда вы знаете, что grep сможет найти целевую строку `--Tablestructure`? Кроме того, всегда ли целевая строка находится в начале строки? Если это так, то пользовательская программа должна работать даже для произвольно длинных строк (N = длина фиксированной целевой строки): прочитать буфер, найти каждую новую строку по очереди, проверить наличие N символов в буфере после новой строки (иначе сдвинуть новую строку к началу строки). буфер, заполнить оставшуюся часть буфера), проверить целевую строку после новой строки, перейти к следующей новой строке, если не найдено. КМП не нужен.
флаг eg
Если бы данные уже были несжаты в обычном (доступном для поиска) файле, то сработала бы команда `grep -m1`, за которой следует `cat`.
Рейтинг:8
флаг vn
bunzip2 -c backup.sql.bz2 | \
  sed -n '/-- Структура таблицы для `mytable`/,$p'

Объяснение:

-n запретить автоматическую печать пространства шаблонов

Построение диапазона адресов: Начните с регулярного выражения

/-- Структура таблицы для `mytable`/

Конец с

$ Соответствует последней строке.

Команда

p Распечатайте текущее пространство шаблона.

Изменить: в зависимости от того, как вы сбросили базу данных, которая у вас может быть очень длинные линии. GNU sed может обрабатывать их до объема доступной памяти.

флаг de
Действительно, у меня очень длинные очереди. Это 64-битная система, поэтому теоретически она может выделить до 2^64 байт для одного процесса. Но моя физическая память ограничена 64 ГБ, а объем подкачки далеко не соответствует гигабайтному диапазону. Поэтому я думаю, что все пространство шаблонов не поместится в память для этих длинных строк.
Рейтинг:2
флаг de

ПРИМЕЧАНИЕ. Не фактический ответ

Поскольку я был мотивирован решить эту проблему в настоящее время, я пошел дальше и использовал grep найти смещение в нужном мне файле; это сработало отлично.

Бег дд к сожалению, требует, чтобы вы установили сб=1 что в основном означает отсутствие буферизации, а производительность ужасна. В ожидании завершения dd я потратил время на написание собственной программы на C, чтобы пропустить байты. Сделав это, я вижу, что хвост мог бы сделать это для меня так же легко:

$ bunzip2 -c restore.sql.bz2 | хвост -c +[смещение] | bzip2 -c > восстановить-обрезанный.sql.bz2

Я говорю «это не отвечает на мой вопрос», потому что для этого по-прежнему требуется два прохода по файлу: один, чтобы найти смещение того, что я ищу, и другой, чтобы обрезать файл.

Если бы я вернулся к своей пользовательской программе, я мог бы реализовать КМП во время фазы «только чтение» программы, а затем переключиться на «чтение + запись всего» после этого.

Рейтинг:0
флаг cn

Интересно, поможет ли что-то подобное:

использовать строгий;
использовать предупреждения;
использовать функцию «говорить»;

используйте IO::Uncompress::Bunzip2 '$Bunzip2Error';

my $file = $ARGV[0] // умереть "нужен файл";

мой $zh = IO::Uncompress::Bunzip2->new($file, {
    Автозакрытие => 1,
    Прозрачный => 1,
} ) или умереть "Ошибка IO::Uncompress::Bunzip2: $Bunzip2Error\n";

мой триггер $ = undef;
в то время как ( <$zh> ) {
    чавкать;
    $trigger = 1 if $_ eq '-- Сброс данных для таблицы `experiments`';
    сказать, если $триггер;
}

Таким образом, в основном он начинает печатать материал после шаблона, его также можно передать напрямую в bzip2/gzip, например perl Chop.pl input_sql.bz2 | bzip2 > вне.sql.bz2 Вам понадобится libio-сжатие-perl на Дебиан.

флаг de
Это может работать, но может либо не работать, либо не хватать памяти, в зависимости от того, как Perl обрабатывает длинные строки. Я полагаю, что `` в конечном итоге считывает строку полностью в память, и это, вероятно, взорвется. Некоторые из этих строк имеют длину в десятки ГиБ.

Ответить или комментировать

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