使用 bash:将整数的位表示写入文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2746707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
using bash: write bit representation of integer to file
提问by Max Leske
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:
我有一个包含二进制数据的文件,我需要在某个位置替换几个字节。我想出了以下内容来将 bash 定向到偏移量并告诉我它找到了我想要的位置:
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.
这似乎工作得很好,我可以查看在十六进制编辑器中所做的更改。问题是,“anInteger”将被写为该整数的 ASCII 表示(这是有道理的),但我需要编写二进制表示。
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).
我想为此使用 bash,并且脚本应该在尽可能多的系统上运行(我不知道目标系统是否安装了 python 或其他任何系统)。
How do I tell the command to convert the input to binary (possibly from a hex)?
我如何告诉命令将输入转换为二进制(可能来自十六进制)?
采纳答案by cs80
You can use echo to emit specific bytes using hex or octal. For example:
您可以使用 echo 以十六进制或八进制发出特定字节。例如:
echo -n -e \x30
will print ascii 0 (0x30)
将打印 ascii 0 (0x30)
(-n remove trailing newline)
(-n 删除尾随的换行符)
回答by Paused until further notice.
printfis more portable than echo. This function takes a decimal integer and outputs a byte with that value:
printf比 更便携echo。此函数采用十进制整数并输出具有该值的字节:
echobyte () {
if (( >= 0 && <= 255 ))
then
printf "\x$(printf "%x" )"
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
回答by juzejian
xxdis the better way. xxd -r infile outfilewill take ascii hex-value in infile to patch outfile, and you can specify the specific position in infile by this: 1FE:55AA
xxd是更好的方法。xxd -r infile outfile将使用 infile 中的 ascii 十六进制值来修补 outfile,您可以通过以下方式指定 infile 中的特定位置:1FE:55AA
回答by Max Leske
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.
像款待一样工作。我使用以下代码用两个整数(1032 和 1920)替换了 little endian 中字节 24 处的 4 个字节。该代码不会截断文件。
echo -e \x08\x04\x80\x07 | dd of=<file> obs=1 oseek=24 conv=block,notrunc cbs=4
Thanks again.
再次感谢。
回答by Adam
I have a function to do this:
我有一个功能可以做到这一点:
# number representation from 0 to 255 (one char long)
function chr() { printf "\$(printf '%03o' "")" ; return 0 ; }
# from 0 to 65535 (two char long)
function word_litleendian() { chr $(( / 256)) ; chr $(( % 256)) ; return 0 ; }
function word_bigendian() { chr $(( % 256)) ; chr $(( / 256)) ; return 0 ; }
# from 0 to 4294967295 (four char long)
function dword_litleendian() { word_lilteendian $(( / 65536)) ; word_litleendian $(( % 65536)) ; return 0 ; }
function dword_bigendian() { word_bigendian $(( / 65536)) ; word_bigendian $(( % 65536)) ; return 0 ; }
You can use piping or redirection to catch the result.
您可以使用管道或重定向来捕获结果。
回答by nc3b
If you're willing to rely on bc (which is fairly common)
如果你愿意依赖 bc(这很常见)
echo -e "ibase=16\n obase=2 \n A1" | bc -q
might help.
可能有帮助。
回答by WhirlWind
You might put the desired input into a file and use the "if=" option to dd to insert exactly the input you desire.
您可以将所需的输入放入一个文件中,并使用“if=”选项来 dd 准确插入所需的输入。
回答by Vouze
With bash, "printf" has the "-v" option, and all shell has logical operators.
对于 bash,“printf”有“-v”选项,所有的 shell 都有逻辑运算符。
So here is simplier form in bash :
所以这是 bash 中更简单的形式:
int2bin() {
local i=
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"
}
回答by Ray Foulk
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:
就我而言,我需要将十进制数字参数转换为实际的无符号 16 位大端值。这可能不是最有效的方法,但它有效:
# is whatever number (0 to 65535) the caller specifies
DECVAL=
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

