web-dev-qa-db-ja.com

grep結果から部分文字列をgrepする

ログファイルが与えられると、私は通常次のようなことをします:

grep 'marker-1234' filter_log

パターンで ''または ""を使用するか、何も使用しない場合の違いは何ですか?

上記のgrepコマンドは、何千行もの行を生成します。私が望むもの。これらの行の中には、通常、私が求めているデータのチャンクが1つあります。時々、awkを使用して自分が探しているフィールドを印刷します。この場合、ログ形式が変更されます。位置だけに依存することはできません。言うまでもなく、実際のログデータは位置を前方にプッシュできます。

これを理解しやすくするために、ログ行にIPアドレスが含まれているとしましょう。それが私が求めていたすべてだったので、後でそれをパイプして並べ替えて一意にし、集計カウントを取得できます。

例は次のとおりです。

2010-04-08 some logged data, indetermineate chars - [marker-1234] (123.123.123.123) from: [email protected] to [email protected] [stat-xyz9876]

最初のgrepコマンドは、上記のような何千もの行を表示します。そこから、おそらくsedにパイプして、パターンを引き出し、パターンのみを出力できるようにします。

この例では、IPアドレスを使用するだけで十分です。私は試した。 sedは[0-9] {1,3}を理解できませんか。パターンとして?私は[0-9] [0-9] [0-9]しなければなりませんでした。パターン全体が作成されるまで、奇妙な結果が得られました。

これはIPアドレスに固有のものではなく、パターンは変更されますが、学習テンプレートとして使用できます。

皆さん、ありがとうございました。

4
user17245

使用しているOSはわかりませんが、FreeBSD7.0以降ではgrepに-oパターンに一致する部分のみを返すオプション。だからあなたはできる
grep "marker-1234" filter_log | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

'filter_log "からIPアドレスのみのリストを返します...

これは私のシステムでは機能しますが、繰り返しますが、grepのバージョンが何をサポートしているかわかりません。

6
Chris S

これらすべてを1つのawkコマンドで実行できます。他のツールを使用する必要はありません

$ awk '/marker-1234/{for(o=1;o<=NF;o++){if($o~/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)print $o }  }' file
(123.123.123.123)
3
user31894

2番目のgrepは、次のように少し短くすることができます。

grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'

最初の質問に答えるために、二重引用符を使用すると、シェルは変数の展開などのさまざまなことを実行できますが、一部のメタ文字をエスケープする必要がないように保護します。一重引用符は、シェルがこれらの拡張を実行できないようにします。引用符を使用しないと、物事は大きく開かれます。

$ empty=""
$ text1="some words"
$ grep $empty some_file
(It seems to hang, but it's just waiting for input since it thinks "some_file" is 
the pattern and no filename was entered, so it thinks input is supposed to come
from standard input. Press Ctrl-d to end it.)
$ grep "$empty" some_file
(The whole file is shown since a null pattern matches everything.)
$ grep $text1 some_file
grep: words: No such file or directory
some_file:something
some_file:some words
(It sees the contents of the variable as two words, the first is seen as the 
pattern, the second as one file and the filename as a second file.)
$ grep "$text1" some_file
some_file:some words
(Expected results.)
$ grep '$text1' some_file
(No results. The variable isn't expanded and the file doesn't contain a
string that consists of literally those characters (a dollar sign followed
by "text1"))

詳細については、 man bash の「QUOTING」セクションをご覧ください。

xargsコマンドを検索します。次のようなことができるはずです。

grep 'マーカー-1234'filter_log | xargs grep "(" | cut -c1-15

これは正確ではないかもしれませんが、xargsは使用したいコマンドです

1
Jennifer