我需要一个函数来仅在调试期间显示一条消息(函数名称):
#!/bin/bash
debug_function(){
if [[ $DEBUG -eq 1 ]]; then
echo "${FUNCNAME[1]}"
else
DEBUG=0
fi
}
test_function(){
debug_function
echo "something"
}
foo=$(test_function)
echo "Result: $foo"
它可以工作,但在 DEBUG=1 中,函数名称显然会添加到函数输出中。
# sh test
Result: something
# DEBUG=1 sh test
Result: test_function
something
有没有办法只打印一条消息?
使用wall
我得到了正确的行为,但是还有其他选择吗?
谢谢
答案1
您echo "${FUNCNAME[1]}"
打印到 stdout,因此它的输出属于 的输出debug_function
,而后者又属于 的输出test_function
。
将消息打印到 stderr:
通过重定向输出
echo
:echo "${FUNCNAME[1]}" >&2
或者在调用时重定向整个输出
debug_function
(如果整个函数应该只打印到 stderr)debug_function
:debug_function >&2
后一种方法允许将内部命令debug_function
直接打印到标准输出。它们打印的内容将被重定向,因为 stdoutdebug_function
被重定向。
函数本身可以将其 stdout 重定向到其 stderr exec >&2
。这将影响函数中的所有命令。但这也会影响调用函数/脚本,除非重定向函数在子 shell 中运行。
您可以根据需要在子 shell 中运行该函数(debug_function)
。要始终在子 shell 中运行该函数,请在定义该函数时使用()
而不是。{}
因此,一个其全部目的是打印到 stderr 而不是 stdout 的函数可以定义如下:
debug_function()(
exec >&2
echo whatever
# ...
)
Nowecho
和函数中的其他命令不需要>&2
.即使您简单地调用该函数debug_function
,其中的命令也会打印到 stderr。
注意:一个子 shell 或命令的 stdout 或 stderr 可能与另一子 shell 或命令或整个脚本的 stdout 或 stderr 不同。重定向可以在许多级别上实现。因此,如果“正确”的重定向发生在函数体之外,即使是在自己的子 shell 中执行的函数exec >&2
最终也可以写入整个脚本的 stdout。我就不详细说了。
最重要的是要记住:
标准输出通常会被捕获(就像您的情况一样)或进一步通过管道传送。 stderr 的要点是不要让错误/调试/诊断消息污染标准输出。