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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14004756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:08:01  来源:igfitidea点击:

read stdin in function in bash script

bashshellpipebash-function

提问by likern

I have some set of bash functions which output some information:

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

  • find-modelname-in-epson-ppds
  • find-modelname-in-samsung-ppds
  • find-modelname-in-hp-ppds
  • etc ...
  • find-modelname-in-epson-ppds
  • find-modelname-in-samsung-ppds
  • find-modelname-in-hp-ppds
  • 等等 ...

I've been writing functions which read output and filter it:

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

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 ...

But the I thought that it would be better do something like this:

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

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

and then call in another high-level functions:

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

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

How can I achieve that with the best bash practices?

我怎样才能通过最佳 bash 实践实现这一目标?

回答by daveloyall

If the question is How do I pass stdin to a bash function?, then the answer is:

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

Shellscript functions take stdin the ordinary way, as if they were commands or programs. :)

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

input.txt:

输入.txt:

HELLO WORLD
HELLO BOB
NO MATCH

test.sh:

测试.sh:

#!/bin/sh

myfunction() {
    grep HELLO
}

cat input.txt | myfunction

Output:

输出:

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

Note that command line arguments are ALSO handled in the ordinary way, like this:

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

test2.sh:

测试2.sh:

#!/bin/sh

myfunction() {
    grep ""
}

cat input.txt | myfunction BOB

Output:

输出:

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

回答by glenn Hymanman

To be painfully explicit that I'm piping from stdin, I sometimes write

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

cat - | ...

回答by John Kugelman

Call seddirectly. That's it.

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

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

回答by BuvinJ

A very simplemeans to get stdin into a variable is to use read. By default, it reads file descriptor "0", i.e. stdin i.e., /dev/stdin.

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

Example Function:

示例函数:

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

Example implementation:

示例实现:

echo "Hello World" | input               

Result:

结果:

you said Hello World

你说你好世界

Additional info

附加信息

You don't need to declare a variable as being local, of course. I just included that for the sake of good form. Plain old read indoes what you need.

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

So you understand how readworks, by default it reads data off the given file descriptor (or implicit stdin) and blocksuntil it encounters a newline. Much of the time, you'll find that will implicitly be attached to your input, even if you weren't aware of it. If you have a function that seems to "hang", with this mechanism just keep this detail in mind (there are other ways of using readto deal with that).

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

More robust solutions

更强大的解决方案

Adding on the prior example, here's a variation that lets you pass the input via a stdin OR an argument:

添加前面的示例,这里有一个变体,它允许您通过 stdin 或参数传递输入:

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

With that tweak, you could ALSO call the function like:

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

input "Hello World"

How about handling an stdin option plus other multiple arguments? Many standard nix utilities, especially those which typically work with stdin/stdout adhere to the common practice of treating a dash -to mean "default", which contextually means either stdin or stdout, so you can follow the convention, and treat an argument specified as -to mean "stdin":

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

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

Call this like:

像这样调用:

input "Hello" "World"

or

或者

echo "Hello" | input - "World"

Going even further, there is actually no reason to only limit stdin to being an option for only the firstargument! You might create a super flexible function that could use it for any of them...

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

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

Why would you what that? Because you could formulate and pipe inwhatever argument you might need...

你为什么要那样?因为你可以你可能需要的任何参数中制定和管道......

myFunc | input "Hello" -

In this case, I pipe in the 2nd argument using the results of myFuncrather than the only having the option for the first.

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