交换二进制数据

时间:2011-01-29 08:18:41

标签: sed awk swap

我只想将文件的前64个字符与同一个二进制文件的最后64个字符交换。

我该怎么做?

2 个答案:

答案 0 :(得分:0)

我不确定这是否可以用sed或awk可靠地完成。我可以想象一个可以在特定文件上工作的解决方案,或者某些奇怪的条件,例如可能出现换行符。

这在C中相当容易。如果不限于sed或awk,也可以使用shell命令完成:

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

答案 1 :(得分:0)

使用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"

修改

另一种方法是使用xxdsed

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的{​​{1}}选项将行的长度设置为要交换的字节数。
  • xxd - 标签“a”
    • :a - 附加下一行。
    • N - 删除嵌入式换行符
    • s/\n// - 如果它是最后一行输入:
      • \${ - 将最后s/\(.*\)\(.\{$hd\}\)\$/\2\1/个字节交换到开头
      • $hd - 将保留空间中的第一个G字节附加到末尾。由于它是最后一行,因此脚本结束。
    • $n - 结束如果
  • } - 分支标记为“a”。

此外,ba可以对数据进行一些操作。