bash - 在变量中执行命令不执行管道的后半部分

标签 bash variables pipe

我发现从变量扩展的命令不会在管道中运行后面的部分。例如如下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 个参数:helloman .在另一边运行命令 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/

相关文章:

java - 从java在远程机器上运行linux命令

php - "Notice: Undefined variable"、 "Notice: Undefined index"、 "Warning: Undefined array key"和 "Notice: Undefined offset"使用 PHP

从数据库删除时出现 MySQL Date_Sub 问题(使用变量)

c++ - 两个控制台应用程序之间的管道?

c - 从管道读取的字节数

bash - 提取字段到变量

bash - 为什么要测试 "$?"以查看命令是否成功,这是一种反模式?

node.js - 自动同步本地 Github 存储库与服务器上的目录

c# - 从变量实例化泛型类型

bash - 如何在 .screenrc 中转义管道以便在启动时运行命令?