使用 bash:将整数的位表示写入文件

发布于 2024-08-31 02:44:10 字数 463 浏览 7 评论 0原文

我有一个包含二进制数据的文件,我需要替换某个位置的几个字节。我想出了以下方法将 bash 定向到偏移量并告诉我它找到了我想要的位置:

dd bs=1 if=file iseek=24 conv=block cbs=2 | hexdump

现在,使用“文件”作为输出:

echo anInteger | dd bs=1 of=hextest.txt oseek=24 conv=block cbs=2

这似乎工作得很好,我可以查看中所做的更改十六进制编辑器。问题是,“anInteger”将被写为该整数的 ASCII 表示形式(这是有道理的),但我需要编写二进制表示形式。

我想为此使用 bash,并且脚本应该在尽可能多的系统上运行(我不知道目标系统是否安装了 python 或其他系统)。

如何告诉命令将输入​​转换为二进制(可能是十六进制)?

I have a file with binary data and I need to replace a few bytes in a certain position. I've come up with the following to direct bash to the offset and show me that it found the place I want:

dd bs=1 if=file iseek=24 conv=block cbs=2 | hexdump

Now, to use "file" as the output:

echo anInteger | dd bs=1 of=hextest.txt oseek=24 conv=block cbs=2

This seems to work just fine, I can review the changes made in a hex editor. Problem is, "anInteger" will be written as the ASCII representation of that integer (which makes sense) but I need to write the binary representation.

I want to use bash for this and the script should run on as many systems as possible (I don't know if the target system will have python or whatever installed).

How do I tell the command to convert the input to binary (possibly from a hex)?

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

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

发布评论

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

评论(10

别念他 2024-09-07 02:44:11

我有点晚了,但这里有一种仅使用 一个 命令将许多十进制整数转换为二进制的方法:

echobytes() {
    printf $(printf '\\x%x' "$@")
}

首先,嵌套的 < code>printf 将将参数转换为十六进制。诀窍是 printf 将为此处的所有参数使用相同的格式。输出将类似于 \x16\x1\x9a,最后一个字符串将由外部 printf 解释,最终输出您想要的二进制数据!

如果输入超过 255,有多种方法可以对其进行分割,但我没有进一步深入研究,因为它可能取决于字节顺序。

I'm a bit late, but here is a way to convert many decimal integers to binary with only one command:

echobytes() {
    printf $(printf '\\x%x' "$@")
}

First, the nested printf will only convert the arguments to hexadecimal. The trick is printf will use the same format for all the arguments here. The output will be something like \x16\x1\x9a, and that last string will be interpreted by the outer printf, which will finally output the binary data you want!

There are ways to split input if it exceeds 255, but I did not dig in further since it could depend on endianness.

北方的韩爷 2024-09-07 02:44:11

您可以将所需的输入放入文件中,并使用 dd 的“if=”选项来准确插入所需的输入。

You might put the desired input into a file and use the "if=" option to dd to insert exactly the input you desire.

最单纯的乌龟 2024-09-07 02:44:11

就我而言,我需要从十进制数字参数转换为实际的无符号 16 位大端值。这可能不是最有效的方法,但它有效:

# $1 is whatever number (0 to 65535) the caller specifies
DECVAL=$1
HEXSTR=`printf "%04x" "$DECVAL"`
BYTEONE=`echo -n "$HEXSTR" | cut -c 1-2`
BYTETWO=`echo -n "$HEXSTR" | cut -c 3-4`
echo -ne "\x$BYTEONE\x$BYTETWO" | dd of="$FILENAME" bs=1 seek=$((0xdeadbeef)) conv=notrunc

In my case, I needed to go from a decimal numeric argument to the actual unsigned 16-bit big endian value. This is probably not the most efficient way, but it works:

# $1 is whatever number (0 to 65535) the caller specifies
DECVAL=$1
HEXSTR=`printf "%04x" "$DECVAL"`
BYTEONE=`echo -n "$HEXSTR" | cut -c 1-2`
BYTETWO=`echo -n "$HEXSTR" | cut -c 3-4`
echo -ne "\x$BYTEONE\x$BYTETWO" | dd of="$FILENAME" bs=1 seek=$((0xdeadbeef)) conv=notrunc
执手闯天涯 2024-09-07 02:44:10

printfecho 更可移植。此函数采用十进制整数并输出具有该值的字节:

echobyte () {
    if (( $1 >= 0 && $1 <= 255 ))
    then
        printf "\\x$(printf "%x" $1)"
    else
        printf "Invalid value\n" >&2
        return 1
    fi
}

$ echobyte 97
a
$ for i in {0..15}; do echobyte $i; done | hd
00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|
00000010

printf is more portable than echo. This function takes a decimal integer and outputs a byte with that value:

echobyte () {
    if (( $1 >= 0 && $1 <= 255 ))
    then
        printf "\\x$(printf "%x" $1)"
    else
        printf "Invalid value\n" >&2
        return 1
    fi
}

$ echobyte 97
a
$ for i in {0..15}; do echobyte $i; done | hd
00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|
00000010
盛装女皇 2024-09-07 02:44:10

您可以使用 echo 使用十六进制或八进制发出特定字节。例如:

echo -n -e \\x30 

将打印 ascii 0 (0x30)

(-n 删除尾随换行符)

You can use echo to emit specific bytes using hex or octal. For example:

echo -n -e \\x30 

will print ascii 0 (0x30)

(-n remove trailing newline)

捎一片雪花 2024-09-07 02:44:10

xxd 是更好的方法。 xxd -r infile outfile 将采用 infile 中的 ASCII 十六进制值来修补 outfile,您可以通过以下方式指定 infile 中的具体位置:1FE:55AA

xxd is the better way. xxd -r infile outfile will take ascii hex-value in infile to patch outfile, and you can specify the specific position in infile by this: 1FE:55AA

梦魇绽荼蘼 2024-09-07 02:44:10

工作就像一种享受。我使用以下代码将小尾数中字节 24 处的 4 个字节替换为两个整数(1032 和 1920)。该代码不会截断文件。

echo -e \\x08\\x04\\x80\\x07 | dd of=<file> obs=1 oseek=24 conv=block,notrunc cbs=4

再次感谢。

Worked like a treat. I used the following code to replace 4 bytes at byte 24 in little endian with two integers (1032 and 1920). The code does not truncate the file.

echo -e \\x08\\x04\\x80\\x07 | dd of=<file> obs=1 oseek=24 conv=block,notrunc cbs=4

Thanks again.

×纯※雪 2024-09-07 02:44:10

我有一个函数可以做到这一点:

# number representation from 0 to 255 (one char long)
function chr() { printf "\\$(printf '%03o' "$1")" ; return 0 ; }
# from 0 to 65535 (two char long)
function word_litleendian() { chr $(($1 / 256)) ; chr $(($1 % 256)) ; return 0 ; }
function word_bigendian() { chr $(($1 % 256)) ; chr $(($1 / 256)) ; return 0 ; }
# from 0 to 4294967295 (four char long)
function dword_litleendian() { word_lilteendian $(($1 / 65536)) ; word_litleendian $(($1 % 65536)) ; return 0 ; }
function dword_bigendian() { word_bigendian $(($1 / 65536)) ; word_bigendian $(($1 % 65536)) ; return 0 ; }

您可以使用管道或重定向来捕获结果。

I have a function to do this:

# number representation from 0 to 255 (one char long)
function chr() { printf "\\$(printf '%03o' "$1")" ; return 0 ; }
# from 0 to 65535 (two char long)
function word_litleendian() { chr $(($1 / 256)) ; chr $(($1 % 256)) ; return 0 ; }
function word_bigendian() { chr $(($1 % 256)) ; chr $(($1 / 256)) ; return 0 ; }
# from 0 to 4294967295 (four char long)
function dword_litleendian() { word_lilteendian $(($1 / 65536)) ; word_litleendian $(($1 % 65536)) ; return 0 ; }
function dword_bigendian() { word_bigendian $(($1 / 65536)) ; word_bigendian $(($1 % 65536)) ; return 0 ; }

You can use piping or redirection to catch the result.

吾家有女初长成 2024-09-07 02:44:10

如果您愿意依赖 bc (这相当常见)

echo -e "ibase=16\n obase=2 \n A1" | bc -q

可能会有所帮助。

If you're willing to rely on bc (which is fairly common)

echo -e "ibase=16\n obase=2 \n A1" | bc -q

might help.

风情万种。 2024-09-07 02:44:10

在 bash 中,“printf”具有“-v”选项,并且所有 shell 都有逻辑运算符。

所以这是 bash 中更简单的形式:

int2bin() {
  local i=$1
  local f
  printf -v f '\\x%02x\\x%02x\\x%02x\\x%02x' $((i&255)) $((i >> 8 & 255)) $((i >> 16 & 255)) $((i >> 24 & 255))
  printf "$f"
}

With bash, "printf" has the "-v" option, and all shell has logical operators.

So here is simplier form in bash :

int2bin() {
  local i=$1
  local f
  printf -v f '\\x%02x\\x%02x\\x%02x\\x%02x' $((i&255)) $((i >> 8 & 255)) $((i >> 16 & 255)) $((i >> 24 & 255))
  printf "$f"
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文