web-dev-qa-db-ja.com

パイプを使用してbash関数を作成するにはどうすればよいですか?

このように定義された関数はほとんどありません。

function f {
  read and process $1
  ...
  echo $result
}

それらを一緒に構成して、呼び出しがf | g | hのようになるようにします。

引数を処理する関数をstdinからの1つの読み取り引数に変換するためにどのイディオムshoudを使用しますか?ペア、引数のタプルをエスケープする必要なくストリームから読み取ることはできますか(null終了など)?

18
Rumca

可能性のあるアプローチの1つは、関数内に_while...read_構文を配置し、STDINを介して関数に入ってきたデータを処理して操作し、結果のデータをSTDOUTを介して出力することです。

_function X {
  while read data; do
    ...process...
  done
}
_

_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; }
_

ここに、それぞれの機能を示します。

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

$ echo "hi" | logG
G:hi

$ echo "hi" | logH
H:hi
_

ここでそれらを一緒に使用する場合です。

_$ 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
_

さまざまなスタイルの入力を取ることができます。

_#-- 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
_
21
slm

slm's の答えの補足として、関数の引数としてnullで区切られたタプルをいくつか試してみました。

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

注:sayTupleは、ヌル終了レコード-d $'\0'を2回読み取り、入力IFS=の周囲のスペースを処理します。 echo-で囲まれたバックレコード

結果は、\nおよび\tを含むnullで終了する入力を正しく処理することを示しています。

$ printf "%s\0%s\0" "Hello " $' Brave\n\tWorld' | sayTuple 
sayTuple: -Hello - - Brave
        World-

コメントの改善のための提案を追加してください、それは興味深いトピックです。

4
grebneke