bash 的替换和管道有什么区别

bash 的替换和管道有什么区别

我正在运行这两个命令:

echo $(find ./ $OPT1 $OPT2 $OPT3)
echo find ./ $OPT1 $OPT2 $OPT3 | bash

奇怪的是,顶部命令没有产生结果,而底部命令却产生结果。这是为什么?

答案1

第一个运行find ./ $OPT1 $OPT2 $OPT3分词并全局输出( 周围没有引号$()),并将其传递给echo,后者打印它。这与运行命令基本相同find,但换行符会变成空格,并且如果包含find*打印任何文件名?,它们将被扩展。但如果你的内容IFS包含一些不寻常的东西,分词也会同样不寻常。 (另外,$OPT1其他的也没有被引用,所以它们在传递给之前被分割和通配find。)

第二个打印find ./ $OPT1 $OPT2 $OPT3,扩展变量(再次拆分和通配,因为没有引号),并将结果传递给bash,后者将其作为命令运行。再次与运行 几乎相同find,但如果变量包含 shell 元字符,它们将被第二个 shell (再次)扩展。

第一个,请注意文件名foo*已扩展,通配所有三个:

$ touch foo1 foo2 foo\*
$ echo $(find .)
. ./foo2 ./foo* ./foo1 ./foo2 ./foo1

第二,请注意 bash 的管道会导致内部变量扩展,就像您使用的那样eval

$ OPT='echo $BASH_VERSION'
$ echo $OPT
echo $BASH_VERSION
$ echo $OPT | bash
4.3.30(1)-release
$ eval $OPT        # about the same  
4.3.30(1)-release

变量扩展可能是最简单的示例,但它需要一个导出的变量或其他 shell 在任何情况下都具有的变量,如下BASH_VERSION所示。 (我find现在无法想出一个合理的例子。)

根据变量包含的内容,额外的评估轮可能会在是否匹配任何内容OPT方面产生影响。find

相关内容