正如其他人已经说过的,您不能存储/使用 NUL char:
但是,您可以处理任何二进制数据(包括 NUL 字符):
所以回答你的最后一个问题:
谁能给我一个提示,如何在不丢失任何(元)字符的情况下有效地存储或处理包含 \0 字符的字符串?
您可以使用文件或管道有效地存储和处理具有任何元字符的任何字符串。
如果您打算处理数据,您还应注意:
- 只有 NUL 字符会被命令行的变量和参数吃掉,你可以检查一下。
- 请注意,命令替换(as
$(command..)
or `command..`
)除了作为变量之外还有一个额外的扭曲,因为它会吃掉你的结尾新行。
绕过限制
如果你想使用变量,那么你必须通过编码来摆脱 NUL 字符,这里的各种其他解决方案提供了巧妙的方法来做到这一点(一个明显的方法是使用例如 base64 编码/解码)。
如果您担心内存或速度,您可能希望使用最小的解析器并且只引用 NUL 字符(和引用字符)。在这种情况下,这将帮助您:
quote() { sed 's/\\/\\\\/g;s/\x0/\\x00/g'; }
然后,您可以在将您的数据存储在变量和命令行参数中之前保护您的数据,方法是将您的敏感数据传输到quote
中,这将输出一个没有 NUL 字符的安全数据流。echo -en "$var_quoted"
您可以通过使用它将在标准输出上发送正确的字符串来取回原始字符串(带有 NUL 字符) 。
例子:
## Our example output generator, with NUL chars
ascii_table() { echo -en "$(echo '\'0{0..3}{0..7}{0..7} | tr -d " ")"; }
## store
myvar_quoted=$(ascii_table | quote)
## use
echo -en "$myvar_quoted"
注意:用于| hd
获得十六进制数据的清晰视图,并检查您没有丢失任何 NUL 字符。
更换工具
请记住,您可以在不使用命令行中的变量或参数的情况下使用管道走得很远,例如,不要忘记<(command ...)
将创建命名管道(一种临时文件)的构造。
编辑:的第一个实现quote
不正确,无法正确处理由 .\
解释的特殊字符echo -en
。感谢@xhienne 发现了这一点。
EDIT2:第二个实现quote
有错误,因为使用 only \0
than 实际上会吃掉更多的零,因为,\0
和是等价的。所以被. 感谢@MatthijsSteen 发现这个。\00
\000
\0000
\0
\x00