首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如果命令在变量中,则在子subshell中执行管道命令不起作用

如果命令在变量中,则在子subshell中执行管道命令不起作用
EN

Stack Overflow用户
提问于 2012-08-27 01:12:39
回答 2查看 2.3K关注 0票数 2

下面的代码运行良好

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash

while true; do
     echo $(pwd | awk '{print "dir: "$1}')
     sleep 1
done

但我需要命令在一个变量中,如下所示。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash                                                                     

COMMAND=pwd | awk '{print "dir: "$1}'
while true; do
     echo $($COMMAND)
     sleep 1
done

第一个代码片段执行得很好,并打印类似于dir: /present/directory的内容。第二个代码段只打印空行。为什么会这样?我该如何修复它?

我使用的命令没有任何意义。我只需要使用管道,并选择这些命令来演示它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-27 01:16:01

如果你喜欢危险的生活,答案是eval

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash                                                                     

COMMAND="pwd | awk '{print \"dir: \"\$1}'"
while true
do
    echo $(eval $COMMAND)
    sleep 1
done

为什么是危险的?很难控制eval发生了什么,如果您接受来自天真(更不用说恶意)用户的命令字符串,就更难控制了。还要注意,我必须非常小心地将包含命令的字符串引起来。

为什么问题中的版本2不起作用?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
COMMAND=pwd | awk '{print "dir: "$1}'

坦率地说,这行并没有做你认为它做的事情。

它是一个管道,第一个‘COMMAND=pwd’是字符串赋值命令,被视为空命令的环境变量,该命令不向awk发送数据。完成后,$COMMAND中的值是一个空字符串(这既是因为与管道一起使用的子shell,也是因为COMMAND=pwd仅在执行( empty )命令时应用),因此循环回显执行空字符串的结果-这也是一个空字符串。因此出现了一行空白。

这对我很有效,但我在AWK打印输出中添加制表符时遇到了问题,我认为这是因为转义的原因。如果我有COMMAND="ls -l | awk '{print \$8 \$9}'",如何在$8$9之间插入选项卡\t

哦,还有讨厌!

如果在$8$9之间的源代码中有一个制表符,awk会将其视为通用空格,并在输出中将$8$9粘贴在一起。要在输出中获得制表符,需要在两个字段之间使用包含制表符的带引号的字符串或包含\t的带引号的字符串,或者使用带有适当格式字符串的printf()

因此,原则上,您可能需要:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
COMMAND='ls -l | awk '\''{printf "%s\t%s\n", $8, $9}'\'

我切换到字符串两边的单引号,因为它们大多更容易理解。无论您使用单引号还是双引号,命令本身都包含这两个引号,因此您必须考虑如何进行转义。'\''序列是如何将单引号嵌入到单引号字符串中;第一个单引号结束当前的单引号字符串;反斜杠单引号添加单引号,最后一个单引号重新启动一个单引号。末尾的序列'\'也可以写成'\''',但是最后两个引号是一个长度为零的单引号字符串,所以我去掉了它们。

这将生成带有制表符的漂亮输出;您可以通过运行以下命令进行验证:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
eval $COMMAND

echo $(eval $COMMAND)完全取消了所有仔细的间隔,将文件和时间的整个列表展平成一行,每个“单词”与下一个单词之间用空格隔开。

您可以通过使用以下命令强制echo遵守空格(和换行符)来解决此问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
echo "$(eval $COMMAND)"

但这引发了一个问题:“为什么不只使用eval $COMMAND?”

(测试: bash 3.2.48 Mac OS X 10.7.4。)

票数 5
EN

Stack Overflow用户

发布于 2012-08-27 01:17:55

单引号的使用使其中的所有内容都是字面上的。这意味着$不会被计算。

然而,在第二个示例中,您通过说$($COMMAND)来强制重新计算。这会导致'...$1‘再次被处理,这次没有引号。那么--瞧!它起作用了!

您可以通过交换“and”、使用双引号(以及在内部使用\或单引号)来解决此问题。

希望这能帮上忙

J

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12135259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文