bash - 为什么 shell 会忽略通过变量传递给它的参数中的引号字符?

标签 bash variables syntax quoting expansion

<分区>

这些工作如广告所示:

grep -ir 'hello world' .
grep -ir hello\ world .

这些不会:

argumentString1="-ir 'hello world'"
argumentString2="-ir hello\\ world"
grep $argumentString1 .
grep $argumentString2 .

尽管 'hello world' 在第二个示例中被引号括起来,但 grep 将 'hello(和 hello\)解释为一个参数和 world'(和 world)作为另一个,这意味着,在这种情况下,'hello 将是搜索模式并且 world' 将是搜索路径。

同样,只有当参数从 argumentString 变量扩展时才会发生这种情况。在第一个示例中,grep 正确地将 'hello world'(和 hello\world)解释为单个参数。

谁能解释一下这是为什么?是否有适当的方法来扩展字符串变量,以保留每个字符的语法,以便 shell 命令正确解释它?

最佳答案

为什么

当字符串被扩展时,它被拆分成单词,但它不会重新评估以查找特殊字符,例如引号或美元符号或......这是外壳“总是”表现的方式,因为1978 年左右的 Bourne shell。

修复

bash 中,使用数组来保存参数:

argumentArray=(-ir 'hello world')
grep "${argumentArray[@]}" .

或者,如果勇敢/有勇无谋,请使用 eval:

argumentString="-ir 'hello world'"
eval "grep $argumentString ."

另一方面,谨慎往往是勇气中更好的部分,使用 eval 时谨慎胜过勇敢。如果您不能完全控制 eval 的字符串(如果命令字符串中有任何用户输入未经严格验证),那么您将面临潜在的严重问题。

注意 Bash 的扩展顺序在 Shell Expansions 中描述。在 GNU Bash 手册中。请特别注意 3.5.3 Shell 参数扩展、3.5.7 单词拆分和 3.5.9 引用删除部分。

关于bash - 为什么 shell 会忽略通过变量传递给它的参数中的引号字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55366494/

相关文章:

bash - 是什么导致 "Directory not empty"错误?

bash - 为什么在可执行文件或脚本名称之前需要 ./(点斜杠) 才能在 bash 中运行它?

linux - 在 linux shell 中确定当前打开的 URL 的最佳方法

javascript - 对象字面量语法奇怪

python - 在单个语句中在 python 中多次测试单个变量

flash - 救命! Actionscript中令人困惑的语法错误1084,要求使用分号?

mysql - 使用变量列表在查询中选择 "ALL"

mysql - 多次选择MySQL session 变量

Java代码: control variable in for loop

variables - 如何访问全局变量