31

如何清理 bash 脚本中的用户输入,以便我可以将其作为参数传递给另一个 shell 程序?我想防止以下情况:

INPUT="filename;rm -rf /"
ls $INPUT

我在想用双引号将用户输入括起来就足够了,如下所示:

ls "$INPUT"

但是如果有双引号$INPUT怎么办?

还是 bash 已经解决了这个问题?

4

1 回答 1

42

短片

Bash 已经解决了这个问题。引用它就足够了。

ls "$INPUT"

关于 shell 如何解析这一行的粗略指南是:

"ls \"$INPUT\""                     # Raw command line.
["ls", "\"$INPUT\""]                # Break into words.
["ls", "\"filename; rm -rf /\""]    # Perform variable expansion.
["ls", "\"filename; rm -rf /\""]    # Perform word splitting (no change).
["ls", "filename; rm -rf /"]        # Remove quotes.

由于引号,$INPUT变量不会进行分词。将ls寻找一个名为filename; rm -rf /.

如果你没有引用它,那么扩展会以不同的方式进行:

"ls $INPUT"                             # Raw command line.
["ls", "$INPUT"]                        # Break into words.
["ls", "filename; rm -rf /"]            # Perform variable expansion.
["ls", "filename;", "rm", "-rf", "/"]   # Perform word splitting.

您至少可以安慰一下,这实际上不会执行rm -rf /。相反,它会将这些字符串中的每一个作为文件名传递给ls. 你会ls得到一些你不想要的文件,但至少它不会意外执行不需要的命令。

jkugelman$ VAR='.; echo hi'
jkugelman$ ls $VAR
ls: .;: No such file or directory
ls: echo: No such file or directory
ls: hi: No such file or directory

摘自“男人 bash”:

报价

引用用于删除某些字符或单词对 shell 的特殊含义。引号可用于禁用对特殊字符的特殊处理,防止保留字被识别为保留字,并防止参数扩展。

扩张

将其拆分为单词后在命令行上执行扩展。执行的扩展有七种:大括号扩展、波浪号扩展、参数和变量扩展、命令替换、算术扩展、分词和路径名扩展。

只有大括号展开、分词、路径名展开可以改变展开的字数;其他扩展将单个单词扩展为单个单词。唯一的例外是 和 的扩展,"$@"如上所述"${name[@]}"(参见参数)。

分词

shell 会扫描双引号内未出现的参数扩展、命令替换和算术扩展的结果以进行分词。

报价删除

在前面的扩展之后,所有未引用的字符\, ', 和"不是由上述扩展之一产生的都将被删除。

于 2010-11-25T01:54:13.873 回答