パイプを使用してbash関数を作成する方法は?


18

この方法で定義された関数はほとんどありません。

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

呼び出しが次のようになるようにそれらを一緒に作りたいですf | g | h

引数で機能する関数をstdinからの引数を読み取る1つに変換するために使用するイディオムのシャドーは何ですか?ペアをエスケープする必要なくストリームから引数のタプルを読み取ることは可能ですか?


次のようにするh(g(f(...)))か、各関数が標準入力(read x; ...)から読み取り、標準出力()に書き込みますecho ...
フォンブランド14

回答:


21

考えられるアプローチの1つは、while...readSTDINを介して関数に入ってきたデータを処理し、それを操作し、その結果のデータを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

4

slmの答えの補遺として、関数引数としてヌルで区切られたタプルを試してみました:

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

注:inputを囲むスペースを処理sayTupleするヌル終了レコード-d $'\0'を2回読み取りますIFS=echoに囲まれたバックレコード-

それは正確に格納したヌル入力ハンドルショー結果\nとを\t

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

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


あなたのアイデアに+1を付けてください。代わりにループを入れて、任意の#個の引数を取ることができます。sayTuple() { arr=() ; while IFS= read -r -d $'\0' arg; do arr+="$arg"; done; echo "sayTuple: ${arr[@]}"; }
slm

あなたができるはずのようにIFS= read -r -d $'\0' -a arg見えますが、私はこれを動作させることができませんでした。これにより、の削除が可能になりますがwhile、これは不要と思われますが、動作する唯一のパターンでした。
slm
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.