如何在shell函数内直接在标准输出上打印?

36

我在我的脚本中编写了一个函数,用于在控制台上打印消息。它可以从任何其他函数中调用。

function print_message
{
    echo "message content"
}

问题在于,在shell中,像echoprintf这样通常将数据打印到标准输出的函数,会将它们的消息重定向到调用函数作为返回值。
return_value=$(print_message) # this line print nothing.
echo $return_value # This line print the message. I don't want to have to do it.

我希望避免这种行为并直接将其打印到标准输出或错误输出。有没有办法做到这一点?

或者我只是想在shell中使用函数,这样做是错误的,应该使用一个庞大的脚本来处理任何行为吗?


3
你想让print_message的输出总是进入标准错误流吗?那么在函数中重定向到echo "message content" >&2 - Etan Reisner
@EtanReisner - 听起来他们想要在标准输出和标准错误上都有。STDOUT 以便被 $( ... ) 捕获,而 STDERR 则会显示在屏幕上。 - Mr. Llama
@EtanReisner 针对标准错误可以工作,但是能否将其打印到标准输出中?>&1似乎不起作用。 - Aracthor
3
$(...) 语法 捕获 标准输出。这就是你的问题最初出现的地方。它的作用就是如此。在 $(...) 上下文中,你不能将你的函数输出到与其余调用不同的其他标准输出上,除非使用标准错误并/或直接检测并打印到 tty/等。 - Etan Reisner
3个回答

48

$(...) 调用语法捕获标准输出。这就是它的工作。这就是它所做的。

如果你想要不被捕获的静态消息,那么可以使用标准错误(但请不要对不是错误消息或调试消息等的内容这样做)。

你不能拥有一个函数将输出到标准输出,但不会被运行它的 $(...) 上下文所捕获,因为只有一个标准输出流。你最好的选择是检测何时拥有一个控制终端等,并直接向其写入(但我建议大多数情况下也不要这样做)。

要完全将函数重定向到标准错误,您可以执行以下任一操作。

print_message() {
    echo "message content" >&2
}
或者
print_message() {
    echo "message content"
} >&2

如果只有一行输出,这两者之间的差异不重要,但如果有多行输出,则后者很可能会稍微更优化(特别是当输出流恰好是文件时)。

此外,请避免使用function关键字,因为它不符合POSIX / spec,并且不太具有广泛的可移植性。


3
你在明确地说“不要直接打印输出!把它放在一个变量中,以便我能够自己打印它!”。
你可以简单地停止这样做,消息将会自动打印出来:
$ cat yourscript 
#!/bin/bash

function print_message
{
    echo "message content"
}

print_message

$ ./yourscript
message content

谢谢你的建议。在这种情况下我不能使用它,因为我需要存储函数的返回值,但我会记住这个技巧。 - Aracthor
“你可以简单地不这样做”是什么意思? - Peter Mortensen
@PeterMortensen "你可以简单地停止这样做" - that other guy
谁在第一?哇,好的。这就引出了一个问题,你能做到这个吗?print_message | wc。 :-) - Anthony Rutledge

-3
在 $(...) 中调用 print_message 会重定向输出。如果您不想重定向输出,请直接调用命令而不使用 $(...)。例如:
 return_value=print_message # this line print nothing.
 echo $return_value # this line print the message. I don't want to have to do it.

请注意,您提供的函数的返回值现在将成为该函数的名称。

4
这不会调用 print_message。这将通过 echo 行打印出 print_message 的结果。 - Etan Reisner
它对我有效,而我在网上阅读的内容说你只需要输入函数名称来调用它。例如,`function print_message { echo "message content" }print_message print_message`会打印输出两次。 - cacciatc
3
它对你来说可能无法正常工作。请再试一遍并确保您的函数输出除print_message以外的其他内容。是的,在发生函数调用的位置,仅名称就足够了,但return_value=print_message不是一个发生函数调用的位置。请参见http://ideone.com/dnEvPA。 - Etan Reisner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接