以下bash和Perl脚本神秘地给出了不同的结果。为什么呢?
#!/bin/bash
hash=`echo -n 'abcd' | /usr/bin/shasum -a 256`;
echo $hash;
#!/usr/bin/perl
$hash = `echo -n 'abcd' | /usr/bin/shasum -a 256`;
print "$hash";
bash脚本:
$ ./tst.sh
88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589 -
Perl脚本:
$ ./tst.pl
61799467ee1ab1f607764ab36c061f09cfac2f9c554e13f4c7442e66cbab9403 -
哎呀?
答案 0 :(得分:18)
摘要:在您的Perl脚本中,-n
被视为要包含在echo
输出中的参数,而不是用于禁止换行的标志。 (试试
$hash = `echo -n 'abcd'`;
确认)。请改用printf
。
Perl使用/bin/sh
来执行后台抽动中的代码。即使/bin/sh
是bash
的链接,当通过它调用时,它的行为也会有所不同。在POSIX模式下,
echo -n 'abcd'
将输出
-n abcd
也就是说,-n
选项不会被识别为禁止换行的标志,但会被视为要打印的常规参数。在每个脚本中将echo -n
替换为printf
,您应该从每个脚本获得相同的SHA哈希值。
(更新:bash
3.2,当调用为sh
时,会显示此行为。bash
的较新版本似乎会在调用{-n
时将其作为标记继续处理{1}}。)
更好的是,不要在Perl做你可以做的事情。
sh
对于好奇的,这里有关于use Digest::SHA;
$hash = Digest::SHA::sha256('abcd');
的POSIX规范has to say。我不知道如何制作XSI一致性; echo
bash
需要echo
选项专门处理转义字符,但几乎每个shell- 除了旧版-e
,然后只有在特殊情况下 - 将bash
视为标志,而不是字符串。哦,好吧。
-n
答案 1 :(得分:6)
如果你这样做:
printf "%s" 'abcd' | /usr/bin/shasum -a 256
你得到88d ... 589哈希。如果你这样做:
printf "%s\n" '-n abcd' | /usr/bin/shasum -a 256
你得到617 ... 403哈希。
因此,我推断Perl以某种方式运行不同的echo
命令,可能是/bin/echo
或/usr/bin/echo
而不是bash
内置echo
,或者可能是/bin/sh
的内置回声(可能是dash
而不是bash
),而另一个echo
无法识别-n
选项作为选项并输出不同的数据。
我不确定它找到了哪个echo
;在我的运行Ubuntu 14.04 LTE衍生产品的计算机上,bash
,dash
,sh
(已关联到bash
),ksh
,csh
和tcsh
所有人都以同样的方式对待echo -n abcd
。但在某个地方,我认为沿着这些路线发生了一些事情;哈希校验和是相同的强烈指向它。 (也许你有一个与bash
相关联的3.2 sh
;请参阅评论中的注释。)