1

私はしばしばこのようなことをしていることに気づきます:

something | grep cat | grep bat | grep rat

私が覚えているのは、これらの3つの単語が、ある順序で、something...の出力のどこかに発生したに違いないということだけです。これで、次のようなことができます。

something | grep '.*cat.*bat.*rat.*'

しかし、それは順序付けを意味します (バットはネコの後に現れます)。そのため、次のようになる bash 関数を自分の環境に追加することを考えていましたmgrep

mgrep cat bat rat

の中へ

grep cat | grep bat | grep rat

しかし、それを行う方法がよくわかりません(または代替手段があるかどうか)。1 つのアイデアは、次のようにパラメーターを for ループすることです。

while (($#)); do
    grep $1 some_thing > some_thing
    shift
done
cat some_thing

some_thing は>(cmd)、bash で行う場合のような fifo である可能性がありますが、わかりません。どのように進めますか?

4

3 に答える 3

2

各ステップで stdin をリダイレクトすることにより、一度に 1 つのコマンドでパイプラインを生成できると思います。しかし、次のように、パイプラインを文字列として生成し、eval で実行する方がはるかに簡単でクリーンです。

CMD="grep '$1' "  # consume the first argument
shift

for arg in "$@"   # Add the rest in a pipeline
do
  CMD="$CMD | grep '$arg'"
done
eval $CMD

これにより、モデルのように常に標準入力から読み取る grep のパイプラインが生成されます。次のように記述した場合に正しく機能するように、引用符で囲まれた引数のスペースを保護することに注意してください。

mgrep 'the cat' 'the bat' 'the rat'
于 2012-09-08T21:18:52.800 に答える
2

アレクシスのおかげで、これは私がやったことです:

function mgrep() #grep multiple keywords
{
    CMD=''
    while (($#)); do
        CMD="$CMD grep \"$1\" | "
        shift
    done
    eval ${CMD%| }
}
于 2012-09-08T21:27:27.283 に答える
1

再帰関数を書くことができます。基本ケースには満足していませんが、より良いケースは思いつきません。標準入力を標準出力に渡すためだけに呼び出す必要があるのは無駄に思えcatます。while ループは少し洗練されていません。

mgrep () {
    local e=$1;
    # shift && grep "$e" | mgrep "$@" || while read -r; do echo "$REPLY"; done
    shift && grep "$e" | mgrep "$@" || cat

    # Maybe?
    # shift && grep "$e" | mgrep "$@" || echo "$(</dev/stdin)"
}
于 2012-09-08T21:43:23.743 に答える