23 bash quoting command-substitution
是时候解决这个困扰我多年的难题了......
我不时遇到这个问题,并认为这是要走的路:
$(comm "$(arg)")
Run Code Online (Sandbox Code Playgroud)
并认为我的观点得到了经验的强烈支持。但我不再那么确定了。Shellcheck也拿不定主意。两者都是:
"$(dirname $0)"/stop.bash
^-- SC2086: Double quote to prevent globbing and word splitting.
Run Code Online (Sandbox Code Playgroud)
和:
$(dirname "$0")/stop.bash
^-- SC2046: Quote this to prevent word splitting.
Run Code Online (Sandbox Code Playgroud)
背后的逻辑是什么?
(这是 Shellcheck 0.4.4 版,顺便说一句。)
ilk*_*chu 50
您需要使用"$(somecmd "$file")"
.
如果没有引号,带有空格的路径将在参数中拆分为somecmd
,并且它将定位到错误的文件。所以你需要在里面引用。
输出中的任何空格somecmd
也会导致拆分,因此您需要在整个命令替换的外部加上引号。
命令替换内的引号对其外部的引号没有影响。Bash 自己的参考手册对此不太清楚,但BashGuide 明确提到了它。POSIX 中的文本也需要它,因为内部允许“任何有效的 shell 脚本”$(...)
:
对于
$(command)
表单,左括号后面到匹配右括号的所有字符构成命令。任何有效的 shell 脚本都可用于命令,但仅由重定向组成的脚本除外,该脚本会产生未指定的结果。
例子:
$ file="./space here/foo"
Run Code Online (Sandbox Code Playgroud)
一种。没有引号,同时dirname
处理./space
和here/foo
:
$ printf "<%s>\n" $(dirname $file)
<.>
<here>
Run Code Online (Sandbox Code Playgroud)
湾 里面的行情,dirname
过程./space here/foo
,给予./space here
,分为两部分:
$ printf "<%s>\n" $(dirname "$file")
<./space>
<here>
Run Code Online (Sandbox Code Playgroud)
C。Quotes outside,dirname
处理./space
and here/foo
, 在单独的行上输出,但现在这两行形成一个参数:
$ printf "<%s>\n" "$(dirname $file)"
<.
here>
Run Code Online (Sandbox Code Playgroud)
d. 内外引述,这给出了正确的答案:
$ printf "<%s>\n" "$(dirname "$file")"
<./space here>
Run Code Online (Sandbox Code Playgroud)
(如果dirname
只处理第一个参数,那可能会更简单,但这不会显示情况 a 和 c 之间的区别。)
请注意,与dirname
(可能还有其他人)一起,您还需要添加--
, 以防止将文件名作为选项,以防它碰巧以破折号开头,因此请使用"$(dirname -- "$file")"
.