如何像管道链中的常规命令一样使用 bash 函数?

如何像管道链中的常规命令一样使用 bash 函数?

我正在 bash 脚本中对大文件执行多个命令。为了监控进度,我使用 pv 命令。

示例命令可能如下所示

cat $IN_FILE | pv -w 20 -s $(du -sb $IN_FILE | awk '{print $1}') | grep ...

该脚本包含多个具有相似结构的命令,而不必一次又一次地在所有这些命令上使用相同的前缀,我为进度监视部分定义了一个函数作为速记。 (注意:fSize 和 fSize Sum 函数包装了上例中的 du 命令部分,其中 fSizeSum 返回两个文件的大小之和,fSize 返回一个文件的大小):

function prog()
{
    local __size
    if [[ $2 ]]
    then
        __size=$(fSizeSum $1 $2)
    else
        __size=$(fSize $1)
    fi

    echo "cat $1 | pv -w 20 -s ${__size}"
}

实际上,这种方法已经稍微缩短了命令。我现在可以像这样执行上面的示例:

eval "$(prog $IN_FILE) | grep ..."

仍然困扰我的是,我现在必须引用每一行并使用 eval。我宁愿使用函数“prog”,就像它是常规 shell 命令一样,即:

prog $IN_FILE | grep ...

到目前为止,我所有修改函数以作为管道命令链中的前缀的尝试都失败了。

有什么方法可以使自定义的 bash 脚本函数像常规 bash 命令一样运行并将其放在管道链前面吗?如果无法使用函数来实现此目的,是否还有其他方法可以实现此目标 - 例如在脚本中定义本地别名?

答案1

在您的函数定义中,我建议替换:

echo "cat $1 | pv -w 20 -s ${__size}"

只是:

cat $1 | pv -w 20 -s ${__size}

eval这样,函数本身将执行这段代码,而不需要在调用者中进行调用。

答案2

pv行为就像cat您将文件作为参数传递一样,这样您甚至不需要传递 -s。

所以你可以这样做:

pv -w 20 $IN_FILE | grep ...

相关内容