【问题标题】:read stdin in function in bash script在 bash 脚本中读取函数中的标准输入
【发布时间】:2012-12-09 21:31:03
【问题描述】:

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

  • 在 epson-ppds 中查找模型名称
  • 在三星 ppds 中查找型号名称
  • find-modelname-in-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 实践实现这一目标?

【问题讨论】:

  • 有什么区别?只有简洁吗?但我认为function 的定义看起来更有表现力,不是吗?
  • 你说的更具表现力是什么意思?在 this link 中,您会看到它已过时且已弃用(而不是 POSIX)。
  • 您的函数find-modelname-... 的真正外观和作用是什么?也许您应该告诉我们更多信息,以便我们可以建议最佳选择。您显然是在尝试分解一些代码,但我们需要知道它到底是什么。
  • @gniourf_gniourf 您引用的链接说function fname { ... } 很好。不推荐使用的是function fname() {...}
  • @gniourf_gniourf 是的,但正如您所指出的那样,它在 bash 中并未被弃用。无论如何,paren 语法更丑陋而且没有意义;它们不用于调用函数,也不在其中传递参数。

标签: bash shell pipe bash-function


【解决方案1】:

一个非常简单的意思是把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 一起使用的实用程序,都遵循将破折号 - 视为“默认”的常见做法,这在上下文中表示标准输入或标准输出,因此您可以遵循约定,并处理指定为- 的参数表示“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 的结果在第二个参数中输入管道,而不是第一个选项。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 这不适用于 bash 4.1.0。我得到输出:“ HELLO WORLD \n HELLO BOB \n NO MATCH”
    • 好的,这是因为我在输入字符串中使用了\n。我已经编辑了答案;为简单起见,它现在只包含一个输入文件。这个问题是关于从函数访问stdin 的——这部分甚至在 bash 2.05b 中也有效。 :)
    • 啊,是的...因为 echo 不支持转义序列。另一种处理方法是定义一个变量,如 NL="" 并将 "\n" 替换为 "$NL"。现在工作。谢谢!
    • 这对于多命令功能没有意义。例如,分配一个变量,然后调用一个接受标准输入的命令。或者如果我想将标准输入传递给两个不同的函数(à la tee)怎么办?如果您还不知道答案并且有一个更稍微更复杂的案例,那么这里缺乏解释会使这个答案几乎毫无用处。
    • jpmc26,嗨,欢迎来到 Stack Overflow。我希望这个答案不是真的“几乎没用”。问题是关于简单案例的,所以答案也是关于简单案例的。我从未尝试将stdin 传递给包含多个命令的函数。稍后我将在我的 shell 中使用这个想法。同时,如果您有时间,请发布一个新问题。
    【解决方案3】:

    为了明确表示我是从标准输入管道,我有时会写

    cat - | ...
    

    【讨论】:

    • 就我而言,确实我需要“痛苦地明确”,否则它不起作用。
    • @Mahdi 你什么意思?在这种情况下/上下文中是否有需要使用cat - 的外壳?哪一个?什么时候?怎么样?
    • 我有一个脚本在 Hadoop map-reduce 作业中作为映射器运行,输入内容通过标准输入提供给我。我需要将整个输入读入一个文件以进行进一步处理,这个解决方案对我有用。
    • 这应该是一个可以接受的答案。它简短、简单,最重要的是,直截了当。基本上,cat 的手册页建议这样做。或者只是cat | ,但这不太明确。
    【解决方案4】:

    直接致电sed。就是这样。

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

    【讨论】:

      猜你喜欢
      • 2021-07-06
      • 1970-01-01
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多