【问题标题】:How to store the output of a command in a variable at the same time as printing the output?如何在打印输出的同时将命令的输出存储在变量中?
【发布时间】:2016-09-01 06:17:52
【问题描述】:

假设我想echo 某事并将其捕获到一个变量中,同时我在我的屏幕上看到它。

echo "hello" | tee tmp_file
var=$(< tmp_file)

所以现在我可以在终端中看到 hello 并将其保存到变量 $var 中。

但是,有什么方法可以做到这一点而不必使用临时文件? tee 似乎不是解决方案,因为它说(来自man tee从标准输入读取并写入标准输出和文件,而这里是标准输出的两倍。

如果这很重要,我在 Bash 4.3 中。

【问题讨论】:

  • @xhienne 其实这个问题更清楚,答案很好,但也有一些无用的噪音。
  • @oguzismail 不,这些答案充其量只是误导。当一个人真正想写信给stdout时,不应该写信给/dev/tty/dev/tty 可能根本不存在。
  • @xhienne 我明白了。 This one 不写信给/dev/tty。同样,可能根本不支持进程替换。
  • @oguzismail 这正是其他答案更好的原因。在这里,您必须挖掘直到最不赞成的答案才能找到正确的答案。在那里,接受的答案是正确的,如果您的 bash 太旧而无法提供命令替换,那么第二个和第三个答案就可以解决问题。

标签: bash stdout gnu


【解决方案1】:

将其发送到标准错误。

var="$(echo "hello" | tee /dev/stderr)"

或者将 stdout 复制到更高的 FD 并发送到那里。

$ exec 10>&1
$ var="$(echo "hello" | tee /proc/self/fd/10)"
hello
$ echo "$var"
hello

【讨论】:

  • 嗯,很有趣。你能详细说明一下FD部分吗? exec 10&gt;&amp;1 对我来说听起来很奇怪。
  • @fedorqui: exec 在 bash 中有两个用途。首先是用新的进程替换当前的进程。第二种是使用重定向语法对文件描述符进行操作。如果未指定命令,则将 FD 重定向应用于当前进程。
  • @fedorqui &amp;1 指向/proc/self/fd/1,后者指向/dev/pts/1,即终端屏幕。这会将/proc/self/fd/10 指向与/proc/self/fd/1 相同的文件,即终端屏幕。这意味着当它是 tee 时,它​​直接进入终端,而 stdout(&1) 被分配拾取。这是一个迂回的方式,只是开球到/dev/pts/1
【解决方案2】:

使用 tee 将其直接引导到屏幕而不是标准输出

$ var=$(echo hi | tee /dev/tty)
hi
$ echo $var
hi

【讨论】:

  • 这行得通,这正是提问者所要求的。请注意,如果您的脚本的调用者正在使用标准输出,他们将看不到您发送到 /dev/tty 的内容(这应该很明显,但它让我感到困惑,所以我想我会分享)。
  • 这肯定会破坏换行符
  • @vladkras 不,如果你想保留空格/特殊字符,请引用变量
  • @123 你刚刚为我节省了半个小时的调试时间……
【解决方案3】:

管道tee 可以解决问题。

这是我在this question 中提到的方法。

var=$(echo "hello" | tee /dev/tty)

然后你可以使用$var来取回存储的变量。

例如:

var=$(echo "hello" | tee /dev/tty); echo "$var world"

将输出:

hello
hello world

你可以用管道做更多的事情,例如我想在终端打印一个短语,同时告诉其中有多少个“l”:

count=$(echo "hello world" | tee /dev/tty | grep -o "l" | wc -l); echo "$count"

这将打印:

hello world
3

【讨论】:

  • 这与我的回答有何不同?
  • @123 对于这个特定的问题,没有。但是,在我上面提到的问题中,我还有另一个比这个更复杂的要求。我自己想通了。所以OP也邀请我在这里发帖。就是这样。
  • 也感谢您发布答案!有趣的是,一切都发生得如此之快:你回答另一个问题,我在这里问,@123 发布他的答案。现在我们将所有信息都放在同一个地方,更容易找到。谢谢大家!
【解决方案4】:

Ignacio 答案的一个变体:

$ exec 9>&1                                                                                                              
$ var=$(echo "hello" | tee >(cat - >&9))   
hello                                                                              
$ echo $var
hello

详情请看:https://stackoverflow.com/a/12451419/1054322

【讨论】:

  • 非常好,因为它不依赖于 proc 文件系统上的特定文件名(即也适用于 MacOS)。 exec 10&gt;&amp;1 在 zsh 上失败(并关闭 shell,因为它将 10 解释为替换 shell 的命令(然后失败,因为 10 不是有效命令)但将 10 替换为 9,一切正常: ) : exec 9&gt;&amp;1
猜你喜欢
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
  • 2011-08-20
  • 2015-03-10
  • 1970-01-01
  • 2014-10-21
相关资源
最近更新 更多