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

lik*_*ern 38 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 ...
Run Code Online (Sandbox Code Playgroud)

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

function filter-general {
    (somehow get input) | sed <bla-blah-blah>
}
Run Code Online (Sandbox Code Playgroud)

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

function high-level-func {
    # outputs filtered information
    find-modelname-in-hp/epson/...-ppds | filter-general 
}
Run Code Online (Sandbox Code Playgroud)

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

dav*_*all 47

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

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

input.txt中:

HELLO WORLD
HELLO BOB
NO MATCH
Run Code Online (Sandbox Code Playgroud)

test.sh:

#!/bin/sh

myfunction() {
    grep HELLO
}

cat input.txt | myfunction
Run Code Online (Sandbox Code Playgroud)

输出:

hobbes@metalbaby:~/scratch$ ./test.sh 
 HELLO WORLD 
 HELLO BOB 
Run Code Online (Sandbox Code Playgroud)

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

test2.sh:

#!/bin/sh

myfunction() {
    grep "$1"
}

cat input.txt | myfunction BOB
Run Code Online (Sandbox Code Playgroud)

输出:

hobbes@metalbaby:~/scratch/$ ./test2.sh 
 HELLO BOB 
Run Code Online (Sandbox Code Playgroud)

  • jpmc26,嗨,欢迎来到 Stack Overflow。我希望这个答案不是真的“几乎没用”。问题是关于简单的情况,所以答案也是关于简单的情况。我从未尝试通过管道将 `stdin` 传递给包含多个命令的函数。稍后我会在我的 shell 中使用这个想法。同时,如果您有时间,请发布一个关于此的新问题。 (2认同)

Buv*_*inJ 16

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

示例函数:

input(){ local in; read in; echo you said $in; }                    
Run Code Online (Sandbox Code Playgroud)

示例实现:

echo "Hello World" | input               
Run Code Online (Sandbox Code Playgroud)

结果:

你说你好世界

附加信息

当然,您不需要将变量声明为本地变量。我只是为了良好的形式而将其包括在内。简单的老read in做你需要的。

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

更强大的解决方案

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

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

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

input "Hello World"
Run Code Online (Sandbox Code Playgroud)

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

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

像这样调用:

input "Hello" "World"
Run Code Online (Sandbox Code Playgroud)

或者

echo "Hello" | input - "World"
Run Code Online (Sandbox Code Playgroud)

更进一步,实际上没有理由仅将 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
}
Run Code Online (Sandbox Code Playgroud)

你为什么要那样?因为您可以制定并输入您可能需要的任何论点......

myFunc | input "Hello" -
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我在第二个参数中使用的结果进行管道传输,myFunc而不是唯一具有第一个选项的选项。


gle*_*man 15

要痛苦地说明我是从斯坦丁那里来的,我有时会写

cat - | ...
Run Code Online (Sandbox Code Playgroud)

  • 这应该是一个可以接受的答案。它简短、简单,最重要的是,开门见山。基本上,“cat”的手册页建议这样做。或者只是“猫|” `,但这不太明确。 (2认同)

Joh*_*ica 5

sed直接打电话.而已.

function filter-general {
    sed <bla-blah-blah>
}
Run Code Online (Sandbox Code Playgroud)