在bash脚本中读取函数中的stdin

时间:2012-12-22 17:02:29

标签: bash shell pipe bash-function

我有一些bash函数可以输出一些信息:

  • 找到-MODELNAME-在爱普生-PPDS
  • 找到-MODELNAME-在三星-PPDS
  • 找到-MODELNAME-在-HP-PPDS
  • 等...

我一直在编写读取输出并过滤它的函数:

function filter-epson {
    find-modelname-in-epson-ppds | sed <bla-blah-blah>
}

function filter-hp {
    find-modelname-in-hp-ppds | sed <the same bla-blah-blah>
}
etc ...

但我认为最好做这样的事情:

function filter-general {
    (somehow get input) | sed <bla-blah-blah>
}

然后调用另一个高级函数:

function high-level-func {
    # outputs filtered information
    find-modelname-in-hp/epson/...-ppds | filter-general 
}

如何通过最好的bash实践实现这一目标?

4 个答案:

答案 0 :(得分:42)

如果问题是How do I pass stdin to a bash function?,那么答案是:

Shellscript函数以普通的方式使用stdin,就好像它们是命令或程序一样。 :)

input.txt中:

HELLO WORLD
HELLO BOB
NO MATCH

test.sh:

#!/bin/sh

myfunction() {
    grep HELLO
}

cat input.txt | myfunction

输出:

hobbes@metalbaby:~/scratch$ ./test.sh 
 HELLO WORLD 
 HELLO BOB 

请注意,命令行参数也是以普通方式处理的,如下所示:

test2.sh:

#!/bin/sh

myfunction() {
    grep "$1"
}

cat input.txt | myfunction BOB

输出:

hobbes@metalbaby:~/scratch/$ ./test2.sh 
 HELLO BOB 

答案 1 :(得分:13)

令人痛苦地明确表示我正在从标准输出管道输出,我有时会写

cat - | ...

答案 2 :(得分:5)

直接致电sed。就是这样。

function filter-general {
    sed <bla-blah-blah>
}

答案 3 :(得分:-1)

非常简单意味着将stdin转换为变量是使用read。默认情况下,它读取文件描述符“ 0”,即标准输入,即/dev/stdin

示例功能:

input(){ local in; read in; echo you said $in; }                    

示例实现:

echo "Hello World" | input               

结果:

  

您说过Hello World

其他信息

当然,您不需要将变量声明为局部变量。我只是出于良好形式将其包括在内。普通的read in会满足您的需求。

因此,您了解read的工作方式,默认情况下,它会从给定的文件描述符(或隐式stdin)读取数据,并 blocks 直到遇到换行符。在大多数情况下,即使您不知道输入内容,也会隐式地将其附加到输入中。如果您有一个似乎“挂起”的函数,则使用此机制就可以牢记这一点(还有其他方法使用read来处理此问题)。

更强大的解决方案

在前面的示例中添加了一个变体,可让您通过标准输入或参数传递输入:

input()
{ 
    local in=$1 if [ -z "$in" ]; then read in; fi
    echo you said $in
}

通过这种调整,您还可以像下面这样调用函数:

input "Hello World"

如何处理stdin选项以及其他多个参数?许多标准nix实用程序,尤其是那些通常与stdin / stdout一起使用的实用程序,都遵循将破折号-表示为“默认”的通用做法,即上下文表示stdin或stdout,因此您可以遵循约定,并且将指定为-的参数视为“ stdin”:

input()
{ 
    local a=$1; if [ "$a" == "-" ]; then read a; fi
    local b=$2
    echo you said $a $b
}

这样称呼:

input "Hello" "World"

echo "Hello" | input - "World"

更进一步,实际上没有理由仅将stdin限制为仅 first 参数的选项!您可能会创建一个超级灵活的函数,可以将其用于其中任何一个...

input()
{ 
    local a=$1; if [ "$a" == "-" ]; then read a; fi
    local b=$2; if [ "$b" == "-" ]; then read b; fi
    echo you said $a $b
}

那你为什么呢?因为您可以制定并插入您可能需要的任何参数...

myFunc | input "Hello" -

在这种情况下,我使用myFunc的结果输入第二个参数,而不是唯一使用第一个参数的选项。