Bash-传递输入而没有shell解释参数扩展字符

时间:2014-10-12 21:49:07

标签: bash shell output parameter-passing

所以我有一个脚本,我输入script.sh,然后输入一组if-else语句。像这样:

    script.sh fnSw38h$?2

输出最终回显输入。

但我注意到了$?被解释为0/1,因此输出将回显:

    fnSw38h12

如何阻止shell扩展字符并使其具有面值?

我看了像opt noglob或类似的东西,但它们没有用。 当我这样说时:

    script.sh 'fnSw38h$?2'

它有效。但是当我无法在其中声明变量时,如何在单引号('')中捕获它,如Var ='$ 1'

请帮忙!

3 个答案:

答案 0 :(得分:2)

如何将密码传递给脚本

我从评论中收集到这个脚本的真正目的是验证密码。 如果这是一个重要或敏感的应用程序,你真的应该使用专业的安全工具。如果这个应用程序不敏感或者这只是一个学习练习,那么请继续阅读以便对问题进行初步介绍。

首先,执行此操作:

script.sh fnSw38h$?2

此密码将显示在ps中,并且系统上的任何用户都可以以纯文本显示。

相反,让用户输入密码作为脚本的输入,例如:

#!/bin/sh
IFS= read -r var

此处,read将从键盘收集输入,不受外壳干扰,并且不会出现在ps输出中。

var将有密码供您验证,但您确实不应该在任何地方保存纯文本密码以供您验证。最好通过单向散列放置密码,然后将散列与保存在文件中的内容进行比较。例如:

var=$(head -n1 | md5sum)

在这里,head将读取一行(密码)并将其传递给md5sum,这会将其转换为哈希值。可以将此哈希与此用户密码的已知正确哈希进行比较。 head返回的文本正是用户键入的内容,由shell解除。

实际上,对于已知的散列算法,可以为常见密码制作反向查找表。因此,解决方案是创建一个名为salt的变量,该变量具有一些与用户相关的信息:

var=$( { head -n1; echo "$salt"; } | md5sum)

盐不必保密。只是在那里使查找表更难以计算。

然而,md5sum算法存在一些缺点。因此,应该用更新的哈希算法替换它。在我写的时候,那可能是sha-2变体。

同样,如果这是一个敏感的应用程序,请不要使用自制工具

回答原始问题

  

当我无法在其中声明变量时,如何在单引号('')中捕获它,如Var ='$ 1'

答案是你不需要。例如,考虑一下这个脚本:

#!/bin/sh
var=$1
echo $var

首先,请注意$$$?都是shell变量:

$ echo $$ $? 
28712 0

现在,让我们试试我们的脚本:

$ bash ./script.sh '$$ $?'
$$ $?

这些变量没有扩展,因为(1)当它们出现在命令行中时,它们是单引号,(2)在脚本中,它们被分配给变量而bash不扩展变量递归。换句话说,在echo $var行上,bash会展开$var以获得$$ $?,但它会停止。它没有扩展var中的内容。

答案 1 :(得分:1)

您可以在双引号字符串中转义任何美元符号,这些符号并不意味着引入参数扩展。

var=foo
# Pass the literal string fnSw38h$?2foo to script.sh
script.sh "fnSw38h\$?2$var"

答案 2 :(得分:1)

你无法做你想做的事。在命令行输入的内容(例如脚本的参数)必须采用shell语法,并且在传递给脚本之前将由shell(根据shell的规则)解释。

当有人运行命令script.sh fnSw38h$?2时,shell会将参数解析为文本“fnSw38h”,然后是$?,这意味着“替换最后一个命令的退出状态”,然后是“ 2" 。所以shell会按照它的说法进行操作,它会替换最后一个命令的退出状态,然后将结果交给你的脚本。

您的脚本永远不会收到“fnSw38h $?2”,并且无法恢复该表单中的参数。它接收类似“fnSw38h02”或“fnSw38h12”的内容,因为是用户要求shell传递它的。这可能不是用户想要传递的内容,但正如我所说,命令必须是shell语法,而在shell语法中,未转义和未加引号的$? 意味着“替换最后一个退出状态“。

如果用户想要传递“$?”作为参数的一部分,它们必须在命令行中转义或单引号。周期。