这是什么形式的变量= $(…)


9

以下是什么意思:

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

我对这部分感兴趣:

varible=$(...)

我知道括号用于执行子流程,但是如果将其与一起使用会$怎样?


3
如果您使用的是bash:通过查找手册页,man bash并搜索Command替代
FloHe

Answers:


16

在Bash手册(man bash)中:

   命令替换
       命令替换允许命令输出替换
       命令名称。有两种形式:

              $(命令)
       要么
              `命令`

       Bash通过在子Shell中执行命令来执行扩展
       环境并用标准替换命令替换
       命令的输出,并删除所有尾随的换行符。嵌入式的
       不会删除换行符,但是在单词过程中可能会删除它们
       分裂。命令替换$(cat文件)可以替换为
       等价但更快的$(<文件)。

(本作也是如此所有类似Bourne外壳,即shkshzshbash等,并且zsh还能够捕获数据以这种方式嵌入的NULL字符)

命令

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

会将脚本所在目录的名称(同时还将所有反斜杠更改为正斜杠)分配给变量basedir。输出到标准错误流的任何错误,警告或其他诊断消息仍将显示在终端上($(...)仅捕获命令的标准输出)。

Shell将通过执行最里面的命令替换开始:

echo "$0" | sed -e 's,\\,/,g'

的输出将作为字符串提供给dirname,并将其输出分配给变量basedir

使用双引号确保不会进行单词拆分或文件名混淆,否则当$0(脚本名称(包括用于执行该脚本的路径)在内)包含空格时,您可能会发现脚本失败或产生奇怪的输出字符或文件名通配符(例如?*)。

通常,总是引用扩展名(变量扩展,命令替换和算术扩展)是一个好主意。请参阅此问题及其答案,以很好地解释为什么这是一个好主意。

如果脚本执行为

$ /usr/local/bin/script.sh

然后basedir将获得的值/usr/local/bin

或者,在Cygwin上:

$ bash c:\\Users\\Me\\script.sh

然后basedir将获得的值c:/Users/Me。在这种情况下,命令行上的双反斜杠只是为了从shell中转义单个反斜杠。的实际值$0c:\Users\Me\script.sh

做同样的事情,而无需使用的另一种方式dirnameechosed

basedir="${0//\\//}"
basedir="${basedir%/*}"

谢谢,所以它基本上是从最里面的括号开始解析的,对吗?为什么使用引号?
Maxim Koretskyi

@Maximus正确。我已经用更多信息更新了我的答案。
库萨兰达

也许您应该说“对所有类似伯恩的贝壳都成立”。这样更清晰
Sergiy Kolodyazhnyy

@Serg,请注意,Bourne shell(如/bin/shSolaris 10或更早版本)不支持$(...)
斯特凡Chazelas

@StéphaneChazelas我将合并它。
库萨兰达

6

这意味着运行的是里面括号中的一个子shell返回,作为一个,你的情况将其赋值给varible


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.