为什么这两个bash命令的输出不同?

为什么这两个bash命令的输出不同?,bash,openssl,Bash,Openssl,为什么 KEY=$(echo -ne "\x2e\x9e\x93\x83\x8c\xf5\xeb\x78\x2f\x9e\xd7\xbe\xaa\x27\xf6\x1f\xa5\x35\xe3\x37\x4c\x78\x22\xc9\x11\x24\x20\x22\xa6\x3e\x28\x30") echo -e "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd)" 生产 0000000: d

为什么

KEY=$(echo -ne "\x2e\x9e\x93\x83\x8c\xf5\xeb\x78\x2f\x9e\xd7\xbe\xaa\x27\xf6\x1f\xa5\x35\xe3\x37\x4c\x78\x22\xc9\x11\x24\x20\x22\xa6\x3e\x28\x30")
echo -e "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd)"
生产

0000000: d77d 4050 8184 cbd2 44f0 f6c2 5b95 39d0  .}@P....D...[.9.
0000010: d9b4 bf25 a7ec a4f8 0dac cc00 6b2b 67d4  ...%........k+g.
而且

echo -ne "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary)" | xxd
产生(请注意,与第一个输出相比,字节28缺失)


据我所知,openssl的输出通过管道传输到子shell外部的xxd并不重要。

由于其强大的C基础,UNIX字符串不能容纳NUL
'\0'
字符。如果要处理可能具有
00
字节的原始二进制数据,则需要避免将结果存储在字符串中。在文件和管道中有
00
字节是安全的

echo -e "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd)"
在这里,openssl使用嵌入的
00
字节吐出二进制数据。由于您将输出直接传输到
xxd
,因此数据得到了完美保存,
00
完好无损

echo -ne "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary)" | xxd
在这里,openssl的输出被存储到字符串中,然后通过管道传输到xxd。
$(…)
操作将去掉NUL字符,因为这些字符无法成功地存储在字符串中。如果它没有把它们去掉,第一个NUL将发出字符串结束的信号

无论如何,你可以去掉一层回声
echo“$(command)”
是一种复杂的编写
command
的方法

echo -n aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd

由于其强大的C基础,UNIX字符串不能容纳NUL
'\0'
字符。如果要处理可能具有
00
字节的原始二进制数据,则需要避免将结果存储在字符串中。在文件和管道中有
00
字节是安全的

echo -e "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd)"
在这里,openssl使用嵌入的
00
字节吐出二进制数据。由于您将输出直接传输到
xxd
,因此数据得到了完美保存,
00
完好无损

echo -ne "$(echo -en aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary)" | xxd
在这里,openssl的输出被存储到字符串中,然后通过管道传输到xxd。
$(…)
操作将去掉NUL字符,因为这些字符无法成功地存储在字符串中。如果它没有把它们去掉,第一个NUL将发出字符串结束的信号

无论如何,你可以去掉一层回声
echo“$(command)”
是一种复杂的编写
command
的方法

echo -n aws4_request | openssl dgst -sha256 -hmac "$KEY" -binary | xxd

问题是摘要是二进制的(具体来说,它包含一个零字节),而shell将c字符串作为参数传递给它的命令(例如
echo
),而这些命令不能包含零字节(/null字符)。如果你看一下丢失的字节,它是十六进制的“00”。您可以通过字符串“aws4_request888”更清楚地看到这一点:

在本例中,摘要有三个空字节,它们都消失了

这里唯一真正的解决方案是避免通过shell参数、变量等传递二进制数据(这可能还包括
$KEY
)。(另一方面,管道可以很好地处理二进制文件。)


如果需要在shell中处理二进制数据,请在存储之前将其转换为十六进制(
hexvar=$(somethingthatsproductsbinary | xxd-p
),然后返回到二进制以供使用(
echo“$hexvar”| xxd-r-p | somethingthatspreadsbinary
)。

问题是摘要是二进制的(特别是,它包含一个零字节),而shell将c字符串作为参数传递给它的命令(例如
echo
),这些命令不能包含零字节(/null字符)。如果您查看缺少的字节,它是十六进制的“00”。您可以通过字符串“aws4\u request888”更清楚地看到这一点:

在本例中,摘要有三个空字节,它们都消失了

这里唯一真正的解决方案是避免通过shell参数、变量等传递二进制数据(也可能包括
$KEY
)(另一方面,管道可以很好地处理二进制数据)

如果您需要在shell中处理二进制数据,请在存储之前将其转换为十六进制(
hexvar=$(somethingthatsproductsbinary | xxd-p
),然后返回到二进制以供使用(
echo“$hexvar”| xxd-r-p | somethingthatsheadsbinary