`$( ... )` 和 `( ... )` 有什么区别?
What is the difference between `$( ... )` and `( ... )`?
$( ... )
和 ( ... )
以及 .
(source
) 之间有什么区别?
在开始编写 shell 脚本时,我了解到 $( ... )
是合适的,如果我想使用命令的输出,例如对于一个变量:
size=$( wc -c < /path/to/file )
然后我发现如果我想执行命令(在子shell中),我可以使用( ... )
,等待它退出并使用它的输出文件,喜欢:
( echo -e "a lot of data, if everything worked... ;-)" > /path/to/file )
有趣的是,它也适用于 $( ... )
,但给出了某种神秘的错误消息 scriptname: line 1: : Command not found.
:
$( echo -e "a lot of data, if everything worked... ;-)" > /path/to/file )
为什么 $( ... )
不能完美地适用于这两个用例?考虑到错误消息,我猜原因是这样的:$( ... )
“在 shell 处甚至强制输出一个空输出”,尽管有 none,而 ( ... )
只是执行命令,不关心输出。是吗?
我知道还有.
(别名source
)在当前的shell中执行一个命令,好像和$( ... )
更像, 关于功能。
或者 .
和 ( ... )
之间是否存在更多差异,而不仅仅是在当前或我不知道的子 shell 中执行命令?
$( cmd )
执行 cmd
然后尝试执行其输出。所以
$( echo -e "a lot of data, if everything worked... ;-)" > /path/to/file )
执行将数据写入 /path/to/file
且不产生任何输出的命令。 shell 获取该输出(空字符串)并尝试执行它,生成您看到的错误消息。
只有 运行 命令,无论是否在子 shell 中,在执行这些命令后不涉及与 shell 本身的任何交互。
$ echo echo poo
echo poo
相比之下,命令替换在完成后由 shell 评估:
$ $(echo echo poo)
poo
$ var=$(echo echo poo)
$ echo "$var"
echo poo
$ $(echo "$var") # expands to the first line (but is unnecessarily redundant)
poo
$ $var # more succinct version of the previous line
poo
当然,如果您重定向命令替换的输出,shell 最终会评估一个空字符串。
.
命令(或者,在 Bash 和其他一些 non-POSIX shell 中,它的同义词 source
)计算一系列命令一份文件。这在某种意义上隐约类似于命令替换,但后者允许您捕获和操纵评估结果(在某种意义上,shell 的整个 purpose是计算表达式)。
命令替换实际上可以用于计算任何地方的表达式,而 .
或 subshell 只能在 shell 接受命令的地方使用。看看这些体操:
$ $(echo e)$(echo c)$(echo h)$(echo o) "poo"
poo
$ echo p$(printf x | wc -l | tr -d ' ' | tr '1' 'o')o
poo
$ ech$(echo o poo)
poo
正如您发现的那样,当您希望一组命令共享一些文件描述符时,subshell 会很有用;
( printf '%s\n' 'Subject: hello' \
'MIME-version: 1.0' \
'Content-type: application/octet-stream' \
'Content-transfer-encoding: base64' \
''
base64 binaryfile ) |
sendmail -oi you@example.net
或者如果你想限制一些环境变化的范围;
for subdir in */; do
( cd "$subdir"
condiments=$(cat spice.txt)
export condiments
make -s dinner )
# back in parent dir
# $condiments is back to its old value
# probably unset, and not exported
done
$( ... )
和 ( ... )
以及 .
(source
) 之间有什么区别?
在开始编写 shell 脚本时,我了解到 $( ... )
是合适的,如果我想使用命令的输出,例如对于一个变量:
size=$( wc -c < /path/to/file )
然后我发现如果我想执行命令(在子shell中),我可以使用( ... )
,等待它退出并使用它的输出文件,喜欢:
( echo -e "a lot of data, if everything worked... ;-)" > /path/to/file )
有趣的是,它也适用于 $( ... )
,但给出了某种神秘的错误消息 scriptname: line 1: : Command not found.
:
$( echo -e "a lot of data, if everything worked... ;-)" > /path/to/file )
为什么 $( ... )
不能完美地适用于这两个用例?考虑到错误消息,我猜原因是这样的:$( ... )
“在 shell 处甚至强制输出一个空输出”,尽管有 none,而 ( ... )
只是执行命令,不关心输出。是吗?
我知道还有.
(别名source
)在当前的shell中执行一个命令,好像和$( ... )
更像, 关于功能。
或者 .
和 ( ... )
之间是否存在更多差异,而不仅仅是在当前或我不知道的子 shell 中执行命令?
$( cmd )
执行 cmd
然后尝试执行其输出。所以
$( echo -e "a lot of data, if everything worked... ;-)" > /path/to/file )
执行将数据写入 /path/to/file
且不产生任何输出的命令。 shell 获取该输出(空字符串)并尝试执行它,生成您看到的错误消息。
只有 运行 命令,无论是否在子 shell 中,在执行这些命令后不涉及与 shell 本身的任何交互。
$ echo echo poo
echo poo
相比之下,命令替换在完成后由 shell 评估:
$ $(echo echo poo)
poo
$ var=$(echo echo poo)
$ echo "$var"
echo poo
$ $(echo "$var") # expands to the first line (but is unnecessarily redundant)
poo
$ $var # more succinct version of the previous line
poo
当然,如果您重定向命令替换的输出,shell 最终会评估一个空字符串。
.
命令(或者,在 Bash 和其他一些 non-POSIX shell 中,它的同义词 source
)计算一系列命令一份文件。这在某种意义上隐约类似于命令替换,但后者允许您捕获和操纵评估结果(在某种意义上,shell 的整个 purpose是计算表达式)。
命令替换实际上可以用于计算任何地方的表达式,而 .
或 subshell 只能在 shell 接受命令的地方使用。看看这些体操:
$ $(echo e)$(echo c)$(echo h)$(echo o) "poo"
poo
$ echo p$(printf x | wc -l | tr -d ' ' | tr '1' 'o')o
poo
$ ech$(echo o poo)
poo
正如您发现的那样,当您希望一组命令共享一些文件描述符时,subshell 会很有用;
( printf '%s\n' 'Subject: hello' \
'MIME-version: 1.0' \
'Content-type: application/octet-stream' \
'Content-transfer-encoding: base64' \
''
base64 binaryfile ) |
sendmail -oi you@example.net
或者如果你想限制一些环境变化的范围;
for subdir in */; do
( cd "$subdir"
condiments=$(cat spice.txt)
export condiments
make -s dinner )
# back in parent dir
# $condiments is back to its old value
# probably unset, and not exported
done