「用語」のgrepおよび「別の用語」を除外


28

用語を検索するが、2番目の用語を持つ行を除外するgrep検索を作成しようとしています。複数の-e "pattern"オプションを使用したかったのですが、うまくいきませんでした。

ここに私が試したコマンドとそれが生成したエラーメッセージの例を示します。

grep -i -E "search term" -ev "exclude term"
grep: exclude term: No such file or directory

これ-vは、すべての検索用語/パターンに適用されることを私に縫います。これは実行されますがsearch term、結果には含まれません。

grep -i -E "search term" -ve "exclude term"

除外する他のオプションはありますか、単語の周りの行をgrepする必要がある場合があり、次の操作で「|」を使用して除外する場合 、その単語を削除するだけで、その単語のブロックは削除しません
Learner

回答:


40

to および grep を使用した式には、2つの呼び出しが必要です。

grep -Ei "search term" | grep -Eiv "exclude term"

検索する用語が正規表現ではない場合、-Fより高速な固定文字列一致()を使用します。

grep -F "search term" | grep -Fv "exclude term"

18

grepを2回呼び出す以外に、これを実現する方法は1つしかありません。これには、Perl Compatible Regular Expressions(PCRE)といくつかのかなりハックなルックアラウンドアサーションが含まれます。

barを含む一致を除外してfooを検索するには、次を使用できます。

grep -P '(?=^((?!bar).)*$)foo'

仕組みは次のとおりです。

  • (?!bar)文字列の文字を消費することなく、bar以外のすべてに一致します。その後.、単一の文字を消費します。

  • ^((?!bar).)*文字列の先頭(^)から末尾()まで上記を繰り返します$。一致しないbarため、特定のポイントで遭遇すると失敗し(?!bar)ます。

  • (?=^((?!bar).)*$) 文字列の文字を消費することなく、文字列が前のパターンと一致することを確認します。

  • foo通常どおりfooを検索します。

単語を含まない文字列に一致する正規表現でこのハックを見つけましたか?。でバートKiers'と答え、あなたはどのように動作するか、負の先読みのより詳細な説明を見つけることができます。


いいハック。このトリックはJavaでも機能します。
ラマン

12

これを1つのパスで実行する場合は、grepの代わりにawkを使用できます。

フォーマット:

echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'

例:

  • echo "hello there" | awk '/hello/ && !/there/'

何も返しません。

  • echo "hello thre" | awk '/hello/ && !/there/'

戻り値:hello thre

  • echo "hllo there" | awk '/hello/ && !/there/'

何も返しません。

複数のパターンの場合、括弧を使用してそれらをグループ化できます。

例:

  • echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'

戻り値:hello thre

  • echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'

戻り値:hi thre

  • echo "hello there" | awk '(/hello/ || /hi/) && !/there/'

何も返しません。

  • echo "hi there" | awk '(/hello/ || /hi/) && !/there/'

何も返しません。


1
それは私のために働いたが、私は色= P失われた
レオポルドSanczyk

1
どの出力からの色ですか?lsで色を保持しようとする場合、出力を解析するときは常に「--color = always」引数を使用します(または、通常、テキストを解析するときに常に色を失います)。例: ls --color=always | awk '/hello/ && !/goodbye/'
フィリップリース

回答@Philipをありがとう!前に試しましたが、成功しませんでした。パターンには色付きのテキストがあるため、後で一致しないため、パターンに何らかのカラーコードを含める必要があります。とにかく、あなたの方法は、grep -RUbuntuコマンドラインを使用していくつかのコードファイルで行うことがわかった最速の方法です。
レオポルドサンチク

1

私の実験では、除外用語をgrepまたはにパイプする場合、大きな違いはありませんsed。Sedには、ログファイルの出力をより適切にフィルタリングするためによく使用する他の便利なテキスト置換機能がいくつかあります。sedには非常に多くのフィルターを組み合わせているので、sedを使用します。

wc /var/log/tomcat/tomcat.2013-01-14.log.1 
  1851725

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK / d" -e "/ Login expired / d" | トイレ
24.05user 0.15system 0:25.27経過した95%CPU(0avgtext + 0avgdata 3504maxresident)k
0inputs + 0outputs(0major + 246minor)pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ login OK / d" -e "/ Login expired / d" | トイレ
23.50ユーザー0.16システム0:24.48経過96%CPU(0avgtext + 0avgdata 3504maxresident)k
0inputs + 0outputs(0major + 246minor)pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "ログインOK" -e "ログイン期限切れ" | トイレ
23.08user 0.14system 0:23.55elapsed 98%CPU(0avgtext + 0avgdata 3504maxresident)k
0inputs + 0outputs(0major + 246minor)pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "ログインOK" -e "ログイン期限切れ" | トイレ
23.50user 0.15system 0:25.27経過した93%CPU(0avgtext + 0avgdata 3488maxresident)k
0inputs + 0outputs(0major + 245minor)pagefaults 0swaps
   5614 91168 1186298


3
grep -F代わりにランタイムを比較してみて、必要ない場合grep -Eは使用し-iないでください。
トール

1
しかし、あなたはsed;)を使用して例を提供しません
ベンジャミンR
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.