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/12136948/

相关文章:

用于删除除特定文件和目录之外的所有文件和目录的 Bash 脚本

windows - Git Bash 控制台在打开时崩溃

macos - 外壳错误 "-bash: bad substitution: no closing ` )'"

syntax - 在yaml中写#(在字符串中)

json - jq 以科学记数法重新格式化小数——这可以避免吗?

java |将 Double 拆分为 2 个整数|将 substring 和 valueOf 与 str 缓冲区一起使用时出现错误

javascript - jQuery 类型函数作为变量

java - 在 Java 中访问内部类中的静态最终字段

c++ - 整组四个 C++ 声明符号的名称?

c - 固定大小数组的指针数组的正确 C 语法是什么?