60

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

  • 在 epson-ppds 中查找模型名称
  • 在三星 ppds 中查找型号名称
  • 在 hp-ppds 中查找模型名称
  • ETC ...

我一直在编写读取输出并对其进行过滤的函数:

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

4 回答 4

75

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

Shellscript 函数以普通方式采用标准输入,就好像它们是命令或程序一样。:)

输入.txt:

HELLO WORLD
HELLO BOB
NO MATCH

测试.sh:

#!/bin/sh

myfunction() {
    grep HELLO
}

cat input.txt | myfunction

输出:

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

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

测试2.sh:

#!/bin/sh

myfunction() {
    grep "$1"
}

cat input.txt | myfunction BOB

输出:

hobbes@metalbaby:~/scratch/$ ./test2.sh 
 HELLO BOB 
于 2014-01-06T18:02:16.140 回答
31

为了痛苦地明确表示我正在从标准输入管道传输,我有时会写

cat - | ...
于 2012-12-23T07:51:32.050 回答
21

将stdin 放入变量的一种非常简单read的方法是使用. 默认情况下,它读取文件描述符“0”,即标准输入,即/dev/stdin.

示例功能:

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

示例实现:

echo "Hello World" | input               

结果:

你说你好世界

附加信息

当然,您不需要将变量声明为本地变量。我只是为了形式好而将其包括在内。普通旧read in的可以满足您的需要。

所以你了解它是如何read工作的,默认情况下它会从给定的文件描述符(或隐式标准输入)中读取数据并阻塞,直到遇到换行符。很多时候,您会发现它会隐含地附加到您的输入中,即使您没有意识到这一点。如果您有一个似乎与此机制挂钩的功能,请记住这个细节(还有其他使用方法read来处理......)。

更强大的解决方案

除了基本示例之外,还有一个变体,可让您通过标准输入或参数传递输入:

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

通过该调整,您还可以调用如下函数:

input "Hello World"

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

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 限制为仅用于第一个参数的选项!您可以创建一个超级灵活的功能,可以将它用于其中任何一个......

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而不是唯一的第一个选项。

于 2019-10-18T14:27:11.043 回答
6

直接打电话sed。就是这样。

function filter-general {
    sed <bla-blah-blah>
}
于 2012-12-22T17:08:24.847 回答