如何使一个可以从标准input读取的bash函数?

我有一些脚本的参数工作,他们工作得很好,但我希望他们能够从标准input读取,例如,从一个例子,假设这被称为读:

#!/bin/bash function read() { echo $* } read $* 

现在这个read "foo" "bar" ,但我想用它作为:

 echo "foo" | read 

我如何做到这一点?

您可以使用<<<来获得这种行为。 read <<< echo "text"应该做到这一点。

readlytesting(我不喜欢使用保留字):

 function readly() { echo $* echo "this was a test" } $ readly <<< echo "hello" hello this was a test 

使用pipe道,基于对“Bash脚本,从stdinpipe道读取值”的答案 :

 $ echo "hello bye" | { read a; echo $a; echo "this was a test"; } hello bye this was a test 

编写一个可以读取标准input的函数有点棘手,但是在没有标准input的情况下可以正常工作。 如果您只是尝试从标准input中读取数据,它将会阻塞,直到接收到任何数据,就像在提示中inputcat一样。

在bash 4中,可以通过使用-t选项来read参数0来解决此问题。如果有任何可用的input,但是不会消耗任何input,则成功; 否则,它失败。

这里有一个简单的函数,如果它有标准input的任何东西,就像cat一样,否则就是echo

 catecho () { if read -t 0; then cat else echo "$*" fi } $ catecho command line arguments command line arguments $ echo "foo bar" | catecho foo bar 

这使得标准input优先于命令行参数,即echo foo | catecho bar echo foo | catecho bar会输出foo 。 要使参数优先于标准input( echo foo | catecho bar输出bar ),可以使用更简单的函数

 catecho () { if [ $# -eq 0 ]; then cat else echo "$*" fi } 

(这也有与任何 POSIX兼容的shell,而不仅仅是某些版本的bash )。

结合其他答案到我的工作(这个人为的例子把小写input转换成大写):

  uppercase() { local COMMAND='tr [:lower:] [:upper:]' if [ -t 0 ]; then if [ $# -gt 0 ]; then echo "$*" | ${COMMAND} fi else cat - | ${COMMAND} fi } 

一些例子(第一个没有input,因此没有输出):

 :; uppercase :; uppercase test TEST :; echo test | uppercase TEST :; uppercase <<< test TEST :; uppercase < <(echo test) TEST 

一步步:

  • testing文件描述符0( /dev/stdin )是否被terminal打开

     if [ -t 0 ]; then 
  • testingCLI调用参数

     if [ $# -gt 0 ]; then 
  • 将所有CLI参数回显到命令

     echo "$*" | ${COMMAND} 
  • 否则,如果stdin是pipe道(即不是terminalinput),输出stdin命令( cat -catcat /dev/stdin简写)

     else cat - | ${COMMAND} 

下面是使用printf和标准input的bash中的sprintf函数的示例实现:

 sprintf() { local stdin; read -d '' -u 0 stdin; printf "$@" "$stdin"; } 

用法示例:

 $ echo bar | sprintf "foo %s" foo bar 

这会给你一个想法如何从标准input读取function。