Обмен данными двоичного файла - PullRequest
0 голосов
/ 29 января 2011

Я просто хочу поменять местами первые 64 символа файла с последними 64 символами того же двоичного файла.

Как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 29 января 2011

Использование xxd:

n=64
file=data
tmp=tmp
len=$(wc -c < "$file")
offset=$((len - n))
len=$((offset - n))
xxd -s -$n "$file" | xxd -r -s -$offset > "$tmp"
xxd -s $n -l $len "$file" | xxd -r  >> "$tmp"
xxd -l $n "$file" | xxd -r >> "$tmp"
mv "$tmp" "$file"

Edit:

Другой подход заключается в использовании xxd и sed:

n=64; hd=$((n * 2))
file=data
tmp=tmp
xxd -c $n -p "$file" |
    sed "1{x;d};:a;N;s/\n//;\${s/\(.*\)\(.\{$hd\}\)\$/\2\1/;G};ba" | 
    xxd -r -p > "$tmp"
mv "$tmp" "$file"

Вместо шести вызовов xxd, это два к xxd и один к sed (и меньше операций чтения и записи файлов).

Объяснение команды sed:

  • 1{x;d} - Сохранить первую строку шестнадцатеричных цифр в поле для удержания. Длина строки задается числом байтов для замены, используя параметр -c xxd.
  • :a - Метка "а"
    • N - Добавить следующую строку.
    • s/\n// - Удалить встроенный перевод строки
    • \${ - Если это последняя строка ввода:
      • s/\(.*\)\(.\{$hd\}\)\$/\2\1/ - поменять местами последние $hd байтов
      • G - Добавить первые $n байтов из пробела в конец. Поскольку это последняя строка, сценарий заканчивается.
    • } - конец, если
  • ba - ответвление к метке "a".

Кроме того, sed может выполнять некоторые манипуляции с данными.

0 голосов
/ 29 января 2011

Я не уверен, что это можно сделать надежно с помощью sed или awk. Я могу представить себе решение, которое будет работать с определенным файлом или с некоторыми странными условиями, например, где могут появляться новые строки.

Это довольно легко сделать в C. И если не ограничиваться sed или awk, это можно сделать и с помощью команд оболочки:

n=64
f=/tmp/test
eval $(stat -s $f)
e=$(($st_size - $n))
dd bs=1  count=$n if=$f          iseek=$e of=/tmp/last64
dd bs=$n count=1  if=$f                   of=/tmp/first64
dd bs=1  count=$n if=/tmp/first64 seek=$e of=$f conv=notrunc
dd bs=$n count=1  if=/tmp/last64          of=$f conv=notrunc
...