Изменить заголовок в огромном файле, не перезаписывая весь файл

У меня проблема с огромными файлами данных. Заголовки этих файлов насчитывают 79 строк. После этих строк данные двоичные. Я хочу изменить заголовок с помощью сценария bash. Я использовал sed до сих пор. Проблема в том, что когда я просто хочу изменить заголовок, либо читается и записывается весь файл данных (1), либо процесс прерывается после этих 79 строк (2). Мне нужно изменить заголовок в 8 строк. Поэтому мои команды, относящиеся к этой проблеме:

(1)

sed -i  '1,79 s/ConverterPositionM2C1='"$M2C1"'/ConverterPositionM2C1='"$M2C1N"'/' $FileName

(2)

sed -i -e '79q' -e 's/ConverterPositionM1C2='"$M1C2"'/ConverterPositionM1C2='"$M1C2N"'/' $FileName

Использование первой команды работает во всех случаях, но для больших файлов (20 ГБ) требуется несколько часов. Поскольку я хочу изменить параметры в 8 строках, которые отличаются друг от друга, мне нужно поместить 8 из этих команд в свой скрипт, а выполнение скрипта занимает еще больше времени. Вторая команда копирует только заголовок. Данные потеряны.


person Jarmikala    schedule 03.12.2014    source источник
comment
Критическая проблема: измененный 79-строчный заголовок имеет ту же длину, что и входной заголовок? Если нет, можете ли вы заполнить заголовок, скажем, пробелами, чтобы он был таким для всех будущих изменений?   -  person John1024    schedule 03.12.2014
comment
@John1024 John1024 Я меняю только числовые значения. Но ведь может случиться так, что 100.00000 станет 10.00000 (а не 010.00000). Количество строк остается прежним.   -  person Jarmikala    schedule 03.12.2014
comment
Количество строк не имеет значения. Количество байтов есть. Если вы измените количество байтов в заголовке, то двоичные данные должны быть перемещены. Можно ли изменить 100.00000 на 10.00000 либо с начальным, либо с конечным пробелом, чтобы количество байтов осталось прежним?   -  person John1024    schedule 03.12.2014
comment
@ John1024 Я думаю, это должно быть возможно. Хотя я не уверен, как используемое позднее программное обеспечение для анализа справляется с дополнительной точностью или дополнительным пространством. Я бы предпочел добавить дополнительный 0.   -  person Jarmikala    schedule 03.12.2014
comment
Возможно, вас интересует этот другой вопрос   -  person Jdamian    schedule 03.12.2014
comment
Спасибо за подсказку. Я буду иметь это в виду. На самом деле это не главная проблема сейчас. Моя проблема заключается в том, что в моем коде отнимают много времени. Моя цель - просто изменить заголовок и сохранить эти изменения. Но либо читается весь файл (случай (1)) либо данные теряются (случай (2)). Если я внесу изменения вручную, открытие файла займет некоторое время, но изменения будут мгновенными. Скрипт работает часами.   -  person Jarmikala    schedule 03.12.2014


Ответы (2)


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

Первый шаг — создать заголовок, который вы хотите. Вы можете использовать что-то вроде:

sed 's/old/new/; 79q' "$FileName" >newhdr

Замените s/old/new/ любыми командами подстановки, которые вам нужны, но помните, что когда все будет сделано, длина заголовка в байтах не должна измениться. 79q говорит sed остановиться после того, как он прочитает 79-ю строку. Новый заголовок записывается во временный файл с именем newhdr.

Если newhdr имеет нужную форму, нам нужно изменить ее на месте в $FileName. Это можно сделать с помощью dd следующим образом:

dd conv=notrunc obs=1 if=newhdr of="$NewFile"

conv=notrunct говорит dd не обрезать выходной файл. obs=1 говорит использовать однобайтовые блоки. if указывает входной файл, а of указывает выходной файл. После выполнения этой команды $NewFile будет обновлено на месте.

person John1024    schedule 03.12.2014
comment
спасибо попробую отпишусь по результату - person Jarmikala; 03.12.2014

Мне сообщили о решении. В мире Unix вы можете

echo $NEW_HEADER | cat - <(dd if=$YOUR_FILE bs=1 skip=$HEADER_SIZE_TO_STRIP)

Это читает ваш файл, удаляет количество байтов заголовка и префикс файла с новым заголовком (включая eol).

person Little Alien    schedule 22.06.2016