Perl shasum vs bash shasum

The following bash and Perl scripts mysteriously produce different results. Why?

#!/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 script:

 $ ./tst.sh 88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589 - 

Perl script:

 $ ./tst.pl 61799467ee1ab1f607764ab36c061f09cfac2f9c554e13f4c7442e66cbab9403 - 

heck?

+5
source share
2 answers

Summary. In your Perl script, -n considered as an argument to include echo in the output, and not a flag to suppress a new line. (Try

 $hash = `echo -n 'abcd'`; 

to confirm). Use printf instead.


Perl uses /bin/sh to execute code in reverse tick. Even if /bin/sh is a reference to bash , it will behave differently when called using similar ones. In POSIX mode

 echo -n 'abcd' 

displays

 -n abcd 

that is, the -n option is not recognized as a flag to suppress a new line, but is considered as a normal argument for printing. Replace echo -n with printf in each script, and you should get the same SHA hash from each script.

(UPDATE: bash 3.2, when called as sh , displays this behavior. Newer versions of bash seem to continue to treat -n as a flag when calling sh .)


Better yet, don't do the things you can do in Perl.

 use Digest::SHA; $hash = Digest::SHA::sha256('abcd'); 

For the curious, this is what echo to say . I'm not sure what to do with XSI compatibility; bash echo requires the -e option to handle escape characters on purpose, but almost every shell - except for older versions of bash , and then only under special circumstances - treats -n as a flag, not a string, Oh, fine.

 The following operands shall be supported: string A string to be written to standard output. If the first operand is -n, or if any of the operands contain a <backslash> character, the results are implementation-defined. On XSI-conformant systems, if the first operand is -n, it shall be treated as a string, not an option. The following character sequences shall be recognized on XSI-conformant systems within any of the arguments: \a Write an <alert>. \b Write a <backspace>. \c Suppress the <newline> that otherwise follows the final argument in the output. All characters following the '\c' in the arguments shall be ignored. \f Write a <form-feed>. \n Write a <newline>. \r Write a <carriage-return>. \t Write a <tab>. \v Write a <vertical-tab>. \\ Write a <backslash> character. \0num Write an 8-bit value that is the zero, one, two, or three-digit octal number num. 
+17
source

If you do:

 printf "%s" 'abcd' | /usr/bin/shasum -a 256 

you get the hash 88d ... 589. If you do:

 printf "%s\n" '-n abcd' | /usr/bin/shasum -a 256 

you get a hash of 617 ... 403.

So I conclude that Perl somehow runs another echo command, perhaps /bin/echo or /usr/bin/echo instead of the built-in echo bash , or maybe the built-in echo message for /bin/sh (maybe it can be dash , not bash ), and this other echo does not recognize the -n option as a parameter and displays different data.

I'm not sure what other echo he finds; on my machine running the LTE derivative of Ubuntu 14.04, bash , dash , sh (associated with bash ), ksh , csh and tcsh all handle echo -n abcd in the same way, But somewhere along the line, I think there are something in that direction; identical hash checksums strictly point to it. (Perhaps you have 3.2 bash associated with sh , see notes in the comments.)

+6
source

Source: https://habr.com/ru/post/1203510/


All Articles