微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将 bash shell 脚本的输出作为 shell 命令运行?

如何解决将 bash shell 脚本的输出作为 shell 命令运行?

我有一个名为“test.sh”的 shell 脚本:

#!/usr/bin/env bash

echo "echo 'hello';"

当我运行 ./test.sh 时,它显然给出了以下输出

echo '你好';

在这输出也是一个有效的 shell 语句本身。如果我将这一行复制并粘贴到 shell 上并按 Enter,它会说

你好

到目前为止一切顺利。
但是我想一步到位,所以我尝试了这个:

$(./test.sh)

但是我现在得到:

'你好';

以防万一,我使用的是 macOS 10.15.6 Catalina,它认使用 zsh shell。我在 Linux 上使用 bash 尝试了同样的方法,结果相同。

为了以防万一,我也尝试了 $('./test.sh')$("./test.sh"),但显然没有任何区别。

对此可能有一些简单的解释和解决方案,但我看不到。我做错了什么?


(编辑)也许这两个回声令人困惑,假设我的 test.sh 脚本包含这个:

echo "ls *.txt;"

如果我现在做./test.sh,我会得到

ls *.txt;

如果我将其复制并粘贴到 shell 上,它会按预期显示所有 .txt 文件

但是,如果我执行 $(./test.sh),我会得到:

ls: *.txt;: 没有那个文件或目录

让 test.sh 脚本输出的任何内容作为 shell 命令行执行的正确语法是什么?

解决方法

问题是命令替换($( ) 事情)是在解析命令行的过程中完成的——在解析并应用引号、分号和其他一些东西之后。结果,当这些引号、分号等成为命令行的一部分时,它们做任何有用的事情都为时已晚,它们只是没有特殊含义的普通字符。

这是您真正想要使用 eval 的少数情况之一:

eval "$(./test.sh)"

eval 所做的是对其参数重新运行整个解析过程,因此它们中的任何 shell 语法(引号、分号等)都会被完全解析。双引号是为了防止在命令替换之后但在结果传递给 eval 之前发生的一点点解析,这可能会导致奇怪的效果。

顺便说一句,eval 的名声通常很差,因为它可能导致您不希望被视为 shell 语法的东西(如文件名等)被视为 shell 语法。但在这种情况下,这似乎正是您想要和期望的,所以就是这样。

,

您有一个额外的 echo。这是代码(test.sh):

#!/bin/bash
echo "hello"

然后像这样运行它:$(./test.sh)"$(./test.sh)"。它将启动 hello 命令。如果您希望 test.sh 运行脚本,请在 echo "./hello" 中使用 test.sh(使用 ./)。

要在执行前显示命令,请使用 bash -x test.sh

运行此命令

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。