将管道数据传递给函数

时间:2016-10-05 18:57:25

标签: bash pipe

示例输出

说我有一个功能,a

function a() {
    read -r VALUE

    if [[ -n "$VALUE" ]]; then     # empty variable check
        echo "$VALUE"
    else
        echo "Default value"
    fi
}

因此,要展示该功能的管道:

nick@nick-lt:~$ echo "Something" | a
Something

但是,此功能的管道数据应该是可选的。所以,这也应该是有效的。并提供以下输出:

nick@nick-lt:~$ a
Default value

但是,该函数挂起,因为read命令等待来自stdin的数据。

我尝试了什么

老实说不是很多,因为我对此并不了解,在Google上搜索的回报很少。

从概念上讲,我认为可能有一种方法来推动" stdin流的空(或空白,无论有效)值,以便即使空stdin至少附加/预先添加此值,触发read,然后只需先删除/最后一个字符。我没有办法做到这一点。

问题

如果可能的话,我怎样才能使上述两个场景都适用于函数a,以便管道是可选的?

编辑:道歉,快速撰写的问题。现在应该正常工作。

2 个答案:

答案 0 :(得分:3)

一种方法是检查标准输入(fd 0)是否是终端。如果是这样,请不要阅读,因为这会导致用户输入内容。

function a() {
    value=""

    if [ \! -t 0 ] ; then      # read only if fd 0 is a pipe (not a tty)
        read -r value
    fi

    if [ "$value" ] ; then     # if nonempty, print it!
        echo "$value"
    else
        echo "Default value"
    fi
}

我在cygwin上检查过:a打印“默认值”,echo 42 | a打印“42”。

答案 1 :(得分:0)

两个问题:

  • 句法,在关闭之前需要一个空格]]

  • 算法,您需要-n(非零长度)变量测试,而不是-z(零长度)

所以:

if [[ -n "$VALUE" ]]; then

或者简单地说:

if [[ "$VALUE" ]]; then

由于[[是内置的shell,因此您不必严格需要双引号:

if [[ $VALUE ]]; then

同时避免将所有大写字母用作变量名称,因为这些大写字母通常用于表示环境变量,并且您定义的大写字母可能以某种方式覆盖已存在的变量名称。所以使用小写变量名:

if [[ $value ]]; then

除非你是export - 你的变量,并且严格要求它是大写的,否则也要确保它不会覆盖任何已存在的变量。

此外,我会向read添加超时,例如-t 5持续5秒,如果未输入任何输入,则打印默认值。同时将函数名称更改为更有意义的名称。

执行:

function myfunc () { 
    read -rt5 value
    if [[ "$value" ]]; then 
        echo "$value"
    else 
        echo "Default value"
    fi 
    }

示例:

$ function myfunc () { read -rt5 value; if [[ "$value" ]]; then echo "$value"; else echo "Default value"; fi ;}

$ myfunc
Default value

$ echo "something" | myfunc
something

$ myfunc
foobar
foobar