文字列を含まないGrep正規表現


181

grepsyslogファイルと照合するための正規表現パターンのリストを渡します。それらは通常、IPアドレスとログエントリに一致します。

grep "1\.2\.3\.4.*Has exploded" syslog.log

これ"1\.2\.3\.4.*Has exploded"は、ループで渡した部分のような単なるパターンのリストなので、たとえば "-v"を渡すことはできません。

上記の逆を行おうとすると混乱します。特定のIPアドレスとエラーの行を一致させないので、「!1.2.3.4。*展開されました」は、1.2.3.4以外のsyslog行と一致し、展開されたことを通知します。 。私がしなければならないと一致しないようにIPを含めることができるよう。

StackOverflorで同様の投稿をいくつか見てきましたが、それらは正規表現パターンを使用しているため、で操作できないようですgrep。誰かが実用的な例をgrep教えてくれますか?

更新: これは、次のようなスクリプトで発生しています。

patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"

for i in {1..3}
do
 grep "${patterns[$i]}" logfile.log
done

あるパターンに一致したい場合あれば、特定のパターン以外のすべてに一致したい場合もありますか?(これは奇妙な要件のようですが、何でも)。その場合は、2つの異なるパターンのリストを反復処理してみませんか?
beerbajay

まあ、私は正規表現についてあまり詳しくありません。すべてのロギングデバイスについてこれを知りたくないので、「Has Exploded」をgrepしたくないので、「Has Exploded」と!9.10.11.12を1つのステートメントでどうにかgrepできますか?
jwbensley

ニールが示唆しているように、1つのステートメントで絶対に実行する必要がある場合は、否定的な後読みが有効です。そこで私のコメントを見てください。
beerbajay

@Neilの回答に従って、PCREスタイルの正規表現マッチングと否定先読みアサーションを使用します。PCREのpatterns[3]="\!9\.10\.11\.12.*Has exploded"変更 patterns[3]="(?<!9\.10\.11\.12).*Has exploded"grep "${patterns[$i]}" logfile.log変更 grep -P "${patterns[$i]}" logfile.logは、デフォルトでより多くのメタ文字を想定するため、他のマッチング式からエスケープの一部を削除する必要がある場合があります。
Codex24

回答:


341

grep一致grep -vし、逆を行います。「Aに一致するがBには一致しない」必要がある場合、通常はパイプを使用します。

grep "${PATT}" file | grep -v "${NOTPATT}"

これは、前述のようにループの真ん中に入り、PATTERNをgrepに渡しているだけなので、「-v」は使用できません。PATTERNのリストをループしてgrepに渡しています。
jwbensley

1
実際に使用-vでき、ループで使用できます。おそらく、制限についてより具体的にする必要があるか、スクリプトの動作について誤解している可能性があります。コードを投稿してみてください。
beerbajay

beerbajayに感謝します。コンテキストを説明するために、元の投稿にコードを追加しました。私の今の意味がわかりますか?
jwbensley

この答えは完全に正しいわけではありませんが、あなたはかなりbeerbajayを書いていました、私はループを再考する必要があり、最後に-vを使用しました。ポインタをありがとう;)
jwbensley

1
しかし、AがBで構成されている場合はどうでしょうか。言い換えれば、どのような私はラインを一致させたい場合はなし A ABとのライン?パイプは機能しません。
pawamoy

15
(?<!1\.2\.3\.4).*Has exploded

これを-Pで実行して負の後読み(Perl正規表現)にする必要があるため、コマンドは次のようになります。

grep -P '(?<!1\.2\.3\.4).*Has exploded' test.log

これを試して。先頭にが付いている場合は、負の後読みを使用して行を無視し1.2.3.4ます。お役に立てば幸いです。


1
grepルックアラウンドをサポートしていないと確信しています。Gnu grepを使用しておらず、--Pパラメーターを使用してPCREエンジンを使用する場合を除きます。
Tim Pietzcker、2012年

いいえ、grepはこのタイプの正規表現をサポートしていません。(?!<\ 1 \ 0.2 \ 0.3 \ 0.4)$はgrep -P test.log -bash:予期しないトークン`(」の近くに構文エラー
jwbensley

シェルによって解釈される文字が含まれている場合、正規表現を引用符で囲む必要があります。
beerbajay

正しい引用:grep -P '(?<!1\.2\.3\.4) Has exploded' test.log後読みは、式の一致部分の直前の文字でのみ機能するため、アドレスとメッセージの間に他のものが存在する場合1.2.3.4 FOO Has exploded、これは機能しません。
beerbajay

@TimPietzcker、非常に注意深く。それを質問に追加します。また、.*彼の例にも否定的な後読みがあるので注意してください。間に他のテキストがあると思います。
Neil

2
patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"

for i in {1..3}
 do
grep "${patterns[$i]}" logfile.log
done

同じである必要があります

egrep "(1\.2\.3\.4.*Has exploded|5\.6\.7\.8.*Has died)" logfile.log | egrep -v "9\.10\.11\.12.*Has exploded"    
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.