2017-12-03 11 views
0

を取得私は、この検索を含んでシェルスクリプトがあります。ループでgrepコマンドの出力

find . -type f -exec grep -iPho "barh(li|mar|ag)" {} \; 

を私はgrepコマンドが見つかった各文字列をキャプチャし、それを私が命名作成する機能を送りたいです」パーサー "

parser(){ 
# do stuff with each single grep result found 
} 

どのようにすることができますか? はこの権利ですか?

find . -type f -exec grep -iPho "barh(li|mar|ag)" {parser $1} \; 

私は出力にあなたの関数をエクスポートする必要がある機能

答えて

1

シェルだけが機能を実行できます。実行するにはfindbash -cを使用する必要があります。これはまた、新しいプロセスがそれを見るために関数をエクスポートする必要がある理由です。

parser() { 
    while IFS= read -r line; do 
     echo "Processing line: $line" 
    done <<< "$1" 
} 

export -f parser 
find . -type f -exec bash -c 'parser "$(grep -iPho "barh(li|mar|ag)" "$1")"' -- {} \; 

上記のコードは、file1、file2などのすべての出現を処理する関数に送信します。それは各ラインを1つずつ送信しないため、あなたの関数内のラインをループする必要があります。ファイル内にあなたの正規表現の出現がない場合、まだは空の入力であなたの関数を呼び出します!

parser() { 
    echo "Processing line: $1" 
} 

export -f parser 
find . -type f -exec bash -c 'grep -iPho "barh(li|mar|ag)" "[email protected]" | while IFS= read -r line; do parser "$line"; done' -- {} + 

EDIT:あなたのための最善の解決策ではないかもしれません

はそうのはライン一つずつbash -cの文と本当にプロセス内のループを追加してみましょう非常に素敵でシンプルなソリューションは、@gniourf_gniourfによって提案された bash -cを使用していません:

parser() { 
    echo "Processing line: $1" 
} 

find . -type f -exec grep -iPho "barh(li|mar|ag)" {} + | while IFS= read -r line; do parser "$line"; done 

このアプローチは正常に動作し、は1行ずつ処理します。また、もありませんでは、このアプローチで関数をエクスポートする必要はありません。しかし、あなたを驚かせるかもしれないことを気にする必要があります。

パイプライン内の各コマンドは、それ自身のサブシェルで実行され、parser関数または一般的なwhileの変数割り当ては、そのサブシェルから戻った後に失われます。スクリプトを書く場合は、単純なshopt -s lastpipeで十分であり、現在のシェル環境で最後のpipeコマンドを実行します。以前bash -cの例では、あなたが同じ行動を経験すると、あなたの変数の割り当てが同様に失われること

parser() { 
    echo "Processing line: $1" 
} 

while IFS= read -r line; do 
    parser "$line"; 
done < <(find . -type f -exec grep -iPho "barh(li|mar|ag)" {} +) 

注:または、プロセス置換を使用することができます。

+1

Re。 'while read 'ループ:OPが望むものなら' find ... -exec grep ... {} + |一方、読取りライン。パーサ "$ line"を行います。 doneは良い提案です。 –

+0

@gniourf_gniourf提案していただきありがとうございます!私はあなたが気にしないなら、それを答えに加えました。 – PesaThe

+0

これは私のために働いた: 'find。 -type f -exec grep -iPho "barh(li | mar | ag)" {} \; | IFS = read -r行です。パーサ "$ line"を行います。 done ' ... 「+」の代わりに「\;」が表示されます... と答えました。ありがとう。 –

0

に全体findコマンドの結果を望んでいません。

また、関数を実行するにはbashを呼び出す必要があります。

parser() { 
    echo "GOT: $1" 
} 
export -f parser 

find Projects/ -type f -name '*rb' -exec bash -c 'parser "$0"' {} \; 
+0

私は "find"だけでなく、 "grep"コマンドについても言います。 私はこれを試しました: 'find。 "0}" {} \; ' それは私にエラー –

+0

を与えました。しかし、2ビット欠けているのは 'bash -c'と' export'です;-) –

0

私はsedを使うことをお勧めします。これはテキスト処理を行うためのより強力なツールです。 、ちょうどあなたができる、stdoutに印刷されないたとえば、私は、「HA」として終了行の後に文字列「myparse」を追加したいあなたは本当にファイルを置き換えたい場合は、私は

# echo "haha" > text1 
# echo "hehe" > text2 
# echo "heha" > text3 
# find . -type f -exec sed '/ha$/s/ha$/ha myparse/' {} \; 
haha myparse 
heha myparse 
hehe 

のようにこれを行うことができますこのようにする

# find . -type f -exec sed -i '/ha$/s/ha$/ha myparse/' {} \; 
関連する問題