如何使用管道组合 bash 函数?

Rum*_*mca 20 bash pipe shell-script

我以这种方式定义了几个函数:

function f {
  read and process $1
  ...
  echo $result
}
Run Code Online (Sandbox Code Playgroud)

我想将它们组合在一起,以便调用看起来像f | g | h.

我应该使用什么习语将处理参数的函数转换为来自标准输入的读取参数?是否可以从流中读取成对、参数元组而无需转义它们(例如空终止)?

slm*_*slm 24

一种可能的方法是while...read在您的函数中放置一个构造,该构造将处理通过 STDIN 进入函数的任何数据,对其进行操作,然后通过 STDOUT 将结果数据发回。

function X {
  while read data; do
    ...process...
  done
}
Run Code Online (Sandbox Code Playgroud)

需要注意如何配置while ..read..组件,因为它们将高度依赖于它们能够可靠使用的数据类型。您可能会想出一个最佳配置。

例子

$ logF() { while read data; do echo "[F:$(date +"%D %T")] $data"; done; }
$ logG() { while read data; do echo "G:$data";                    done; }
$ logH() { while read data; do echo "H:$data";                    done; }
Run Code Online (Sandbox Code Playgroud)

这是每个功能本身。

$ echo "hi" | logF
[F:02/07/14 20:01:11] hi

$ echo "hi" | logG
G:hi

$ echo "hi" | logH
H:hi
Run Code Online (Sandbox Code Playgroud)

当我们一起使用它们时,它们就在这里。

$ echo "hi" | logF | logG | logH
H:G:[F:02/07/14 19:58:18] hi

$ echo -e "hi\nbye" | logF | logG | logH
H:G:[F:02/07/14 19:58:22] hi
H:G:[F:02/07/14 19:58:22] bye
Run Code Online (Sandbox Code Playgroud)

他们可以接受各种风格的输入。

#-- ex. #1
$ cat <<<"some string of nonsense" | logF | logG | logH
H:G:[F:02/07/14 20:03:47] some string of nonsense

#-- ex. #2    
$ (logF | logG | logH) <<<"Here comes another string."
H:G:[F:02/07/14 20:04:46] Here comes another string.

#-- ex. #3
$ (logF | logG | logH)
Look I can even
H:G:[F:02/07/14 20:05:19] Look I can even
type to it
H:G:[F:02/07/14 20:05:23] type to it
live
H:G:[F:02/07/14 20:05:25] live
via STDIN
H:G:[F:02/07/14 20:05:29] via STDIN
..type Ctrl + D to stop..

#-- ex. #4
$ seq 5 | logF | logG | logH
H:G:[F:02/07/14 20:07:40] 1
H:G:[F:02/07/14 20:07:40] 2
H:G:[F:02/07/14 20:07:40] 3
H:G:[F:02/07/14 20:07:40] 4
H:G:[F:02/07/14 20:07:40] 5

#-- ex. #5
$ (logF | logG | logH) < <(seq 2)
H:G:[F:02/07/14 20:15:17] 1
H:G:[F:02/07/14 20:15:17] 2
Run Code Online (Sandbox Code Playgroud)


gre*_*eke 5

作为slm答案的附录,我对空分隔的元组作为函数参数进行了一些试验:

$ sayTuple() { 
    IFS= read -r -d $'\0' d1
    IFS= read -r -d $'\0' d2
    echo "sayTuple: -$d1- -$d2-"
}
Run Code Online (Sandbox Code Playgroud)

注意:sayTuple两次读取一个以 null 结尾的记录,-d $'\0'处理 input 周围的任何空格IFS=echo后面的记录被包围-

结果显示它正确处理包含\n和的空终止输入\t

$ printf "%s\0%s\0" "Hello " $' Brave\n\tWorld' | sayTuple 
sayTuple: -Hello - - Brave
        World-
Run Code Online (Sandbox Code Playgroud)

请在评论中添加改进建议,这是一个有趣的话题。