更多 Bash 重定向

作者:Mitch Frazier

每个人都见过 bash 命令中的重定向,这很常见,但是 bash 也允许你在定义函数时定义重定向。 这会导致重定向在每次调用该函数时被评估/执行。 此功能实际上并没有提供任何新功能,只是另一种表达现有功能的方式。

此语法很简单,只需将重定向附加到函数定义的末尾

function testy()
{
        ...
} < testy.in > testy.out 2> testy.err

现在无论何时调用函数testy它的输入将来自testy.in,它的输出将转到testy.out,并且任何错误都将转到testy.err.

由于重定向是在调用函数时评估的,因此重定向可以使用变量,并且变量也在调用函数时进行评估。 所以你可以这样做

#!/bin/bash

function testy()
{
    echo testy westy
} >$out

out=jj1
testy
out=jj2
testy

这会导致函数的输出在每次调用时转到不同的文件。 第一次调用的输出转到jj1,第二次转到jj2:

$ bash j.sh; more jj?
::::::::::::::
jj1
::::::::::::::
testy westy
::::::::::::::
jj2
::::::::::::::
testy westy

正如我之前提到的,这里没有任何真正的新功能,你也可以用这种方式完成同样的事情

#!/bin/bash

function testy()
{
    echo testy westy
}

testy >jj1
testy >jj2

此功能的一种可能用途可能是将所有代码放在main函数中,然后重定向它的错误输出,以确保它始终被捕获

#!/bin/bash

log=kk
function error()
{
    echo "$*" >&2
}
function testy()
{
    error testy westy
}

function testy2()
{
    error testy2 westy2
}

function main()
{
    testy
    testy2
} 2>$log

main

运行此程序会产生

$ bash k.sh ;cat kk
testy westy
testy2 westy2

由于 bash 还允许在{...}块/列表 上包含重定向,因此你可以使用以下方法完成相同的事情

#!/bin/bash

log=mm
function error()
{
    echo "$*" >&2
}
function testy()
{
    error testy westy
}

function testy2()
{
    error testy2 westy2
}

{
testy
testy2
} 2>$log

你也可以在(...)块/列表 上使用重定向,但这会导致命令在子 shell 中执行,这没有必要,并且可能会导致问题,因为子 shell 是一个不同的进程。

如果你想知道是否可以在实际调用中覆盖重定向,答案是否定的。 如果你尝试覆盖它们,发生的一切都是调用中的重定向首先被执行/评估,然后函数定义中的重定向替换它们。 例如,在以下代码中

#!/bin/bash

function testy()
{
    echo testy westy
} >nn1

testy >nn2

调用中指定的输出文件 (nn2) 被创建,但没有任何内容写入其中。

另请注意,管道“重定向”不起作用,但 here documents (此处文档) 起作用

#!/bin/bash

function testy()
{
    while read line
    do
        echo $line
    done
} <<EOF
hello
there
EOF

testy

运行此程序会产生

$ bash o.sh
hello
there

Mitch Frazier 是 Emerson Electric Co. 的嵌入式系统程序员。 自 2000 年代初以来,Mitch 一直是Linux Journal的贡献者和朋友。

加载 Disqus 评论