Sed 交换二进制文件的数据

Sed 交换二进制文件的数据,sed,awk,swap,Sed,Awk,Swap,我只想用同一个二进制文件的最后64个字符交换文件的前64个字符 我如何才能做到这一点?我不确定使用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

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


我如何才能做到这一点?

我不确定使用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

使用
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"
不是六次调用
xxd
,而是两次调用
xxd
,一次调用
sed
(文件读写也更少)

sed
命令的说明:

  • 1{x;d}
    -将十六进制数字的第一行保存在保留空间中。使用
    xxd
    -c
    选项将行的长度设置为要交换的字节数
  • :a
    -标签“a”
    • N
      -追加下一行
    • s/\n/
      -删除嵌入的换行符
    • \${
      -如果是最后一行输入:
      • s/\(.*\)\(.\{$hd\}\)\$/\2\1/
        -将最后的
        $hd
        字节交换到开头
      • G
        -将保留空间中的第一个
        $n
        字节追加到末尾。因为这是最后一行,所以脚本结束
    • }
      -如果
  • ba
    -分支到标签“a”

另外,
sed
可以对数据进行一些操作。

为什么要使用面向文本的工具处理二进制文件?如果是二进制文件,我认为您更可能希望交换64个字节而不是64个字符。(我们生活在一个Unicode世界中,不要假设1个字符=1个字节。)而且,正如@belisarius所说,文本UTIL充其量是处理二进制文件的一个危险选择。这是家庭作业吗?我想说一些关于以vim臭名昭著的“腐败”模式将其加载到vim中的事情,但我不会。哎呀。@Catcall这是正确的选择:你的解决方案对我有用。但是我想知道。bs=1计数=64和计数=64 bs=1相同或不同。在重新交换64字节(保留原始二进制)后,我发现md5sum值不同。为什么是这样的行为?
stat-s
似乎是一个BSD选项。GNU似乎没有<代码>st_size=$(wc-c<$f)可能可以改为使用。stat-c%s是我们可以使用的选项。交叉验证:不管您使用什么,[bs=1 count=64]或[bs=64 count=1],都是一样的。Md5sum也保留了。对于XXD解决方案,我想,使用hextump和-r和-p选项也可以实现同样的效果。又来了。哦,嘿,对不起。我喜欢我的Mac电脑的味道,但我发现它在这里引起了一些混乱。顺便说一句,您不能替换
bs=1 count=64
,因为这样就没有办法(我能想到)找到最后64个字节的开头。在运行两次脚本后,我得到了相同的md5,因此我认为它工作正常。
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"