如何动态使用输出重定向?

Min*_*nix 5 bash io-redirection shell-script

我正在尝试向我的脚本添加调试选项。通常我想隐藏任何输出,比如警告等,所以我把>/dev/null 2>&1很多命令放在后面。

现在,当我想调试我的脚本时,我必须手动删除它们,或者将每个命令放在if ... fi一个$DEBUG变量的测试中。

我认为放入>/dev/null 2>&1一个变量 ( $REDIR) 并写入command arg1 $REDIR可以解决问题。如果我想调试,我只需要$REDIR留空。

但是在我的 shell 上的一个简短测试告诉我,它不会那样工作:

~$ echo "bla" >/dev/null 2>&1
~$ REDIR=>/dev/null 2>&1
~$ echo "bla" $REDIR
bla
~$
Run Code Online (Sandbox Code Playgroud)

由于明显的原因,使用"'周围>/dev/null 2>&1也不起作用。

那么为什么我的想法在这里不起作用?我是否误解了将命令等放入变量并调用它们的内容?

Wou*_*lst 7

重定向不是命令,因此您不能以这种方式执行它。如果您使用eval,您可以完成它,但这是打开一罐蠕虫。

一个更好的方法来做你想做的事情是有一个调试输出的功能:

function debugprint {
    if [ ! -z "$debug" ]; then
        echo "$1"
    fi
}

debugprint "$(echo 'bla' 2>&1)"
Run Code Online (Sandbox Code Playgroud)

这会将标准错误重定向到标准输出,然后debugprint将输出作为参数调用。现在您需要做的就是$debug在要调试时将其设置为非空。

当然,这也打开了一个(不同的)蠕虫罐头(与引用有关)。您可能只想使用set -x它,这可能会也可能不足以满足您的调试需求。


yae*_*shi 5

出于这样的目的,我通常定义一个类似 的函数run。在大多数情况下,这可以正确处理带有空格和其他参数的参数。

#!/bin/bash

run() {
        if $DEBUG; then
                v=$(exec 2>&1 && set -x && set -- "$@")
                echo "#${v#*--}"
                "$@"
        else
                "$@" >/dev/null 2>&1
        fi
}

DEBUG=false
run echo "bla"

DEBUG=true
run echo "bla"
run printf "%s . %s . %s\n" bla "more bla" bla
Run Code Online (Sandbox Code Playgroud)

输出:

$ bash debug.sh 
# echo bla
bla
# printf '%s . %s . %s\n' bla 'more bla' bla
bla . more bla . bla
Run Code Online (Sandbox Code Playgroud)