交换二进制数据

发布于 2024-10-15 01:13:37 字数 62 浏览 2 评论 0原文

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

我怎样才能做到这一点?

I just want to swap the first 64 characters of a file with the last 64 characters of the same binary file.

How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陌上芳菲 2024-10-22 01:13:37

我不确定这是否可以用 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

I'm not sure if this can be done reliably with sed or awk. I can imagine a solution that would work on a specific file, or with certain odd conditions like where newlines might appear.

This is fairly easy to do in C. And if not restricted to sed or awk, it can be done with shell commands, too:

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
山有枢 2024-10-22 01:13:37

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

而不是对 xxdxxd 为 2 个,sed 为 1 个(文件读写也更少)。

sed 命令说明:

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

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

Using 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:

Another approach would be to use xxd and 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"

Instead of six calls to xxd, it's two to xxd and one to sed (and fewer file reads and writes, too).

Explanation of the sed command:

  • 1{x;d} - Save the first line of hex digits in hold space. The length of the line is set to the number of bytes to swap using the -c option of xxd.
  • :a - Label "a"
    • N - Append the next line.
    • s/\n// - Remove the embedded newline
    • \${ - If it's the last line of input:
      • s/\(.*\)\(.\{$hd\}\)\$/\2\1/ - Swap the last $hd bytes to the beginning
      • G - Append the first $n bytes from hold space onto the end. Since it's the last line, the script ends.
    • } - end if
  • ba - Branch to label "a".

Additionally, sed could do some manipulation of the data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文