如何在当前shell中执行命令的输出?

时间:2009-08-14 20:13:55

标签: bash shell unix pipe

我很清楚source(又名.)实用程序,它将从文件中获取内容并在当前shell中执行它们。

现在,我正在将一些文本转换为shell命令,然后运行它们,如下所示:

$ ls | sed ... | sh

ls只是一个随机的例子,原始文本可以是任何东西。 sed也是一个转换文本的例子。有趣的是sh。我将我得到的任何东西送到sh并运行它。

我的问题是,这意味着启动一个新的子shell。我宁愿让命令在我当前的shell中运行。就像我可以用source some-file一样,如果我在文本文件中有命令。

我不想创建临时文件,因为感觉很脏。

或者,我想启动我的子shell,其特性与我当前的shell完全相同。

更新

好吧,使用反引号的解决方案肯定有效,但我经常需要在检查和更改输出时这样做,所以我更喜欢是否有办法将结果输入到最后。

悲伤的更新

啊,/dev/stdin看起来很漂亮,但是,在更复杂的情况下,它不起作用。

所以,我有这个:

find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/git mv -f $1 $2.doc/i' | source /dev/stdin

确保所有.doc个文件的扩展名都是小写的。

顺便提一下,可以使用xargs来处理,但这不是重点。

find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/$1 $2.doc/i' | xargs -L1 git mv

所以,当我运行前者时,它会马上退出,没有任何反应。

9 个答案:

答案 0 :(得分:114)

出于此目的,存在eval命令。

eval "$( ls | sed... )"

来自bash manual的更多内容:

  

<强> EVAL

          eval [arguments]
     

参数连接在一起   成一个命令,哪个   然后读取并执行,以及它   退出状态作为退出返回   评估状态。如果没有   参数或只有空参数,   退货状态为零。

答案 1 :(得分:78)

$ ls | sed ... | source /dev/stdin

更新:这适用于bash 4.0,以及tcsh和dash(如果您将source更改为.)。显然这是bash 3.2中的错误。来自bash 4.0 release notes

  

修正了一个导致`。'的错误。无法从非常规文件(如设备或命名管道)读取和执行命令。

答案 2 :(得分:34)

哇,我知道这是一个老问题,但最近我发现自己遇到了同样的问题(这就是我到达这里的方式)。

无论如何 - 我不喜欢source /dev/stdin答案,但我认为我发现了一个更好的答案。实际上看起来很简单:

echo ls -la | xargs xargs

很好,对吗?实际上,这仍然没有做你想要的,因为如果你有多行,它会将它们连接成一个命令而不是分别运行每个命令。所以我找到的解决方案是:

ls | ... | xargs -L 1 xargs

-L 1选项意味着每个命令执行使用(最多)1行。 注意:如果您的行以尾随空格结尾,它将与下一行连接!因此,请确保每一行以非空格结束。

最后,你可以做到

ls | ... | xargs -L 1 xargs -t

查看执行的命令(-t是详细的)。

希望有人读到这个!

答案 3 :(得分:26)

尝试使用process substitution,它将命令的输出替换为可以获取的临时文件:

source <(echo id)

答案 4 :(得分:6)

我相信这是这个问题的“正确答案”:

ls | sed ... | while read line; do $line; done

也就是说,可以管道进入while循环; read命令命令从stdin获取一行,并将其分配给变量$line$line然后成为循环中执行的命令;并继续直到输入中没有其他行。

这仍然不适用于某些控制结构(如另一个循环),但在这种情况下它符合要求。

答案 5 :(得分:5)

`ls | sed ...`

我觉得ls | sed ... | source -会更漂亮,但遗憾的是source无法理解-表示stdin

答案 6 :(得分:1)

我认为您的解决方案是使用反引号替换命令:http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html

见3.4.5节

答案 7 :(得分:0)

为什么不使用source

$ ls | sed ... > out.sh ; source out.sh

答案 8 :(得分:0)

要在bash 3.2(macos)上使用mark4o的解决方案,可以使用此字符串代替此示例中的管道:

. /dev/stdin <<< "$(grep '^alias' ~/.profile)"