我需要制作一个相当简单的 bash 脚本,从二进制文件中一次提取一个字节,将其发送到串行端口,然后等待一个字节返回,然后再发送下一个字节。这对于 EEPROM 编程器来说非常有效,因为现成的解决方案无法工作。
我主要致力于将字节从文件中提取到变量中,除此之外我知道我可以将值回显到串行端口并使用 dd 读回它们。 (还有更好的方法吗?)
谢谢您的帮助!
答案1
使用dd
or xxd
(Vim 的一部分),例如从二进制文件中读取-l
偏移量 100 ( ) 处的一个字节 ( ) 尝试:-s
xxd -p -l1 -s 100 file.bin
要使用十六进制偏移量,在 Bash 中您可以使用以下语法$((16#64))
,例如:
echo $((16#$(xxd -p -l1 -s $((16#FC)) file.bin)))
它在偏移处读取字节FC
并以十进制格式打印它。
或者使用dd
,例如:
dd if=file.bin seek=$((16#FC)) bs=1 count=5 status=none
它将在十六进制偏移处转储 5 个字节的原始数据FC
。
然后你可以将它分配给变量,但是它当您的数据有 NULL 字节时将不起作用,因此您可以跳过它们 ( xxd -a
),或者作为解决方法,您可以将它们存储为纯十六进制格式。
例如:
将偏移量 10 处的 10 个字节读入包含十六进制格式字节的变量:
hex=$(xxd -p -l 10 -s 10 file.bin)
然后将它们写入文件或设备:
xxd -r -p > out.bin <<<$hex
以下是 Bash 中的一些有用的函数:
set -e
# Read single decimal value at given offset from the file.
read_value() {
file="$1"
offset="$2"
[ -n "$file" ]
[ -n "$offset" ]
echo $((16#$(xxd -p -l1 -s $offset "$file")))
}
# Read bytes in hex format at given offset from the file.
read_data() {
file="$1"
offset="$2"
count="$3:-1"
xxd -p -l $count -s $offset "$file"
}
使用示例:
read_value file.bin $((16#FC)) # Read 0xFC offset from file.bin.
答案2
我不确定我是否理解您所要求的总体情况,但我有几种您可能需要考虑的方法:
用于dd
读取您的输入文件
执行3<输入文件 虽然是真的 做 dd bs=1 count=1 <&3 > this_byte 如果 ! [ -s this_byte ] # 如果大小为零,我们就完成了。 然后 休息 菲 代码使用这个字节文件 ︙ 完毕
用于od
消化您的输入文件
OD-BV输入文件|同时读取a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 do # 跳过 $a0;这是地址。 对于“$a1”“$a2”“$a3”“$a4”“$a5”“$a6”“$a7”“$a8”“$a9”“$a10”中的 byte_val \ “$a11” “$a12” “$a13” “$a14” “$a15” “$a16” 做 如果[“$byte_val”=“”] 然后 休息 菲 代码使用$byte_val价值 例如:echo -e "\0$byte_val\c" ︙ 完毕 完毕
答案3
使用一个小型 C 程序或 Python 或 Perl 等脚本语言中的(几乎)一行代码可能更容易做到这一点。
Unix shell 是一个用户命令的解释器,(为了方便编写重复命令)具有基本的编程设施。它经常被(误)使用,因为 Bourne shell 的一个版本是保证它可以在任何 Unix 系统上使用,并不是因为它是一种特别好的(甚至是半途而废的)编程语言。
答案4
您可以使用perl
:
$ printf '%s%s%s' 'ăâé' | LC_ALL=C.UTF-8 perl -Mopen=locale -ne '
BEGIN { $/ = \1 }
printf "%s\n", $_;
'
ă
â
é