我发现从变量扩展的命令不会在管道中运行后面的部分。例如如下test.sh
:
#!/bin/bash
y='echo hello man | awk "{print \$1}"'
$y
eval $y
y='echo hello'
$y
脚本的输出是:
hello man | awk "{print \$1}"
hello
hello
第一个
$y
只执行echo hello man
但不执行awk "{print $1}"
的管道。这就是为什么?我的 bash 版本是
4.3.48
.
最佳答案
那是因为在管道和重定向已经完成之后变量被扩展了。所以在那种情况下|
只是 echo
的另一个参数,而不是由 shell 解释的管道。
推荐阅读:http://mywiki.wooledge.org/BashFAQ/050
执行命令时
echo hello man | awk '{print $1}'
shell 将看到
|
并设置一个管道,在一侧它将运行命令 echo hello man
另一方面awk '{print $1}'
.然后命令会进行分词,因此您运行命令 echo
有 2 个参数:hello
和 man
.在另一边运行命令 awk
使用单个参数(由于引用)"{print \$1}"
当该命令存储为字符串时,shell 首先查看命令
$y
并且看不到重定向要做。然后展开 $y
然后对其进行分词。它被扩展为相同的字符串,但现在重定向为时已晚。所以它被拆分成 echo
, hello
, man
, |
, awk
, "{print
, \$1}"
(注意 awk
的参数现在被拆分,因为字符串中的引号是字符串的一部分,而不是语法)该列表中的第一个单词是
echo
所以这就是命令,所有其余的单词都作为参数传递给它,这就是你看到输出的原因hello man | awk "{print \$1}"
当您执行
eval
行,它采用相同的字符串并告诉 bash
解析它,就好像它已经被输入一样,所以管道再次成为语法并导致管道。因为
echo
把它的论点放在同一条线上,如果我们用 printf '%s\n'
替换它,有时会更难看到发生了什么。但是,每个参数都将成为自己的行:$ y='printf %s\n hello man | awk "{print \$1}"'
$ $y
hello
man
|
awk
"{print
\$1}"
关于bash - 在变量中执行命令不执行管道的后半部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51563838/