我正在尝试用 dd 做一些技巧。我认为可以将一些十六进制值存储在名为“header”的变量中,以将其通过管道传输到 dd 中。
我没有变量的第一步是这样的:
$ echo -ne "\x36\xc9\xda\x00\xb4" |dd of=hex
$ hd hex
00000000 36 c9 da 00 b4 |6....|
00000005
之后我尝试了这个:
$ header=$(echo -ne "\x36\xc9\xda\x00\xb4")
$ echo -n $header | hd
00000000 36 c9 da b4 |6...|
00000004
正如你所看到的,我失去了变量的\x00
值$header
。有人对这种行为有解释吗?这真让我抓狂。
答案1
您不能在字符串中存储空字节,因为 Bash 使用 C 样式字符串,它为终止符保留空字节。因此,您需要重写脚本以简单地通过管道传输包含空字节的序列,而 Bash 不需要将其存储在中间。例如,您可以这样做:
printf "\x36\xc9\xda\x00\xb4" | hd
顺便说一句,请注意,您不需要echo
;您可以使用 Bashprintf
来完成许多其他简单的任务。
或者,您可以使用临时文件来代替链接:
printf "\x36\xc9\xda\x00\xb4" > /tmp/mysequence
hd /tmp/mysequence
当然,这有一个问题,即该文件/tmp/mysequence
可能已经存在。现在您需要继续创建临时文件并将其路径保存在字符串中。
或者您可以通过使用进程替换来避免这种情况:
hd <(printf "\x36\xc9\xda\x00\xb4")
操作<(command)
符在文件系统中创建一个命名管道,它将接收command
.hd
将接收该管道的路径作为其第一个参数——它将打开并读取该管道几乎就像任何文件一样。你可以在这里读更多关于它的内容:https://unix.stackexchange.com/a/17117/136742。
答案2
您可以使用zsh
唯一可以在其变量中存储 NUL 字符的 shell。该字符甚至恰好位于$IFS
in的默认值中zsh
。
nul=$'\0'
或者:
nul=$'\x0'
或者
nul=$'\u0000'
或者
nul=$(printf '\0')
但请注意,您不能将此类变量作为参数或环境变量传递给以下命令:被处决因为参数和环境变量是传递给execve()
系统调用的 NUL 分隔字符串(系统 API 的限制,而不是 shell)。然而,在 中zsh
,您可以将 NUL 字节作为参数传递给函数或内置命令。
echo $'\0' # works
/bin/echo $'\0' # doesn't
答案3
Bash 内部使用 C 字符串,无法存储空字节。将值存储在临时文件中,如下所示:
zHex=$(mktemp --tmpdir "$(basename "$0")-XXXX")
trap "rm -f ${zHex@Q}" EXIT
变量 zHex 现在包含唯一的文件名。 $zHex 引用的文件可以手动删除,但当程序因任何原因终止时,该文件将被自动删除。
然后像这样使用变量:
echo -ne "\x36\xc9\xda\x00\xb4" > "$zHex"
hd "$zHex"
这不会将带有空字节的值存储到变量中。相反,它使用变量来存储文件名。该文件与任何其他文件一样,可能包含空字节并且可以反复使用。文件本身很可能永远不会被物理写入磁盘。
通过陷阱,bash 会自动删除该文件,因此您不必担心手动删除它,除非您正在创建一个疯狂的垃圾数组。由于 RAM 缓冲,该技术相当快。
答案4
由于回车符可以是文件名的一部分,因此我喜欢使用空终止列表。但我无法存储带有空字节的字符串,因为 bash 因为 Bash 将字符串存储为简单的 C 字符串,其中空字节是字符串终止符,因此不能是字符串本身的一部分。
为了解决这个问题,我创建了一个字符串数组,其中假定每个元素后都存在空字节。列表本身显然包含空字节。我将包含空字节的值存储在这样的数组中...
readarray -d $'\0' zArray < <(null_terminated_list_maker)
然后,我可以像这样使用空字节重现该值......
[[ "${zArray[*]}" ]] && printf '%s\0' "${zArray[@]}"
通过这种方式,bash 数组可用于存储任何包含空字节的值。
目的[[ "${zArray[*]}" ]]
是查看数组是否有任何值(空字符串是一个值)。该测试解决了以下问题:如果像这样将空数组传递给 printf,则 printf 将打印一个空字节,这是错误的。它不应该打印任何内容。
当表示完全任意的数据时,存在一个问题:您的输入实际上是否以空字节终止?该方法需要扩展以处理可能或可能不以空字节结尾的数据。