ログファイルのURLからクエリ文字列を取得する

ログファイルのURLからクエリ文字列を取得する

次の形式の多くのログエントリを含むサーバーログファイルがあります。

193.1.172.46 - - [23/Mar/2008:03:57:38 +0000] "GET /robots.txt HTTP/1.0" 404 289 "-" "gsa-crawler (Enterprise; M2-N7RQ5RABCA2JT; [email protected],[email protected])"

Google検索エンジンを使用してすべてのアイテムを識別し、そのアイテムからクエリ文字列を取得し、出力にクエリ文字列のみを表示するように求められました。

したがって、grepコマンドを使用して、次のように検索エンジンにアクセスするすべてのエントリを識別しました。

 grep "http://www.google.com/search?" logs.txt 

これにより、次の項目のリストが表示されます。

143.183.121.3 - - [23/Mar/2008:00:16:59 +0000] "GET /staff/jcarthy/home/2ndYearUnix/usefulcommands2col.pdf HTTP/1.0" 200 78866 "http://www.google.com/search?hl=en&q=frequently+used+unix+aliases&btnG=Google+Search"; "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1)"

これで、アイテムのみを表示するリストのhl=en&q=frequently+used+unix+aliases&btnG=Google+Search部分のみを表示するにはどうすればよいですか?

ベストアンサー1

他のすべての回避策は、参照フィールド内のスペースや追加の引用符、バックスラッシュ、大文字のドメイン名、httpの代わりにhttpsまたは参照フィールド内の場所フィールド、キーワードなどの特定のログエントリで失敗する可能性があります。

たとえば、

1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /a b/ HTTP/1.0" 200 0 "http://www.google.com/search?..." "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /i/love/http://www.google.com/search?ing HTTP/1.0" 200 0 "http://www.google.com/search?..." "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET / HTTP/1.0" 200 0 "http://www.google.com/search?spaces in referrer" "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /nohttpver" 200 0 "http://www.google.com/search?spaces in referrer" "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /" 200 0 "http://example.org/http://www.google.com/search?spaces in referrer" "Mozilla/4.0"
1.2.3.4 - - [23/Mar/2008:00:16:59 +0000] "GET /" 200 0 "http://WWW.GOOGLE.COM/search?spaces in referrer" "Mozilla/4.0"

これらの問題を解決するため、まず、2番目の二重引用符フィールドを正しく抽出する必要があります。。 Apacheログファイルはバックスラッシュを使用して追加の引用符やその他の特殊文字をエスケープします。これは、単純な正規表現(たとえば)だけでは十分では"[^"]*"ないことを意味します。

grepを使用して、引用符付きフィールド(二重引用符で囲まれた2番目のフィールド)を抽出します。

grep -oP '^[^"]+"[^"\\]*(?:\\.[^"\\]*)*"[^"]+"\K[^"\\]*(?:\\.[^"\\]*)*(?=")' logfile.txt

クレイジーだと思います!分析してみましょう。

  • この主張は、私たちが行の残りの部分ではなく一致する部分だけを得ることをo意味します。grep
  • 引数はPerl準拠の正規表現を使用するように指示Pします。grep
  • ここで使用される正規表現の全体構造は、全体の...\K...(?=...)パターンを確認しますが、\Kとの間にあるものだけを出力するという意味です。(?=...)

正規表現をさらに分析すると、次のようになります。

  1. ^[^"]+- 行の先頭と最初の行の間のすべてを取得します。"
  2. "[^"\\]*(?:\\.[^"\\]*)*"- 二重引用符で囲まれた最初の文字列全体を取得します。この答えを見てくださいhttps://stackoverflow.com/a/5696141/1764245
  3. [^"]+- 2つの文字列の間のすべてを取得します。
  4. "\K[^"\\]*(?:\\.[^"\\]*)*(?=")上記と同じですが、\K最初の後に"データの一致を開始し、(?=")最後の前のデータの一致を停止します"

その後、引用符を気にする必要がなくなり、ログファイルからフィールドを正しく抽出する必要がなくなり、データ操作が簡単になります。

たとえば、出力を別のgrepにパイプすることができます。

grep -oP ... logfile.txt | grep -oPi '^https?://www\.google\.com/search\?\K.*'

ここで、i2番目のgrepオプションは大文字と小文字を区別しません。

google.comあるいは、最初の正規表現に直接リファラーを起動するためのチェックを追加して必要\Kに応じて移動することもできますが、2つの正規表現を実行すると、1つのタスクを実行して1つに統合するよりも優れたパフォーマンスが得られるため、これに反対することをお勧めします。責任が不明な場所。

他のGoogleドメインからリファラーを収集するには、正規表現を少し変更する必要があります。 Googleが所有多くの検索フィールド

Google以外のサイトを見つける可能性がある場合は、次のようにします。

... | grep -oPi '^https?://(www\.)?google\.[a-z]{2,3}(\.[a-z]{2})?/search\?\K.*'

それ以外の場合は、移動先のGoogleが所有する検索ドメインのみを一致させようとする必要があります。

... | grep -oPi '^https?://(www\.)?google\.(a[cdelmstz]|b[aefgijsty]|cat|c[acdfghilmnvz]|co\.(ao|bw|c[kr]|i[dln]|jp|k[er]|ls|m[az]|nz|t[hz]|u[gkz]|v[ei]|z[amw])|com(\.(a[fgiru]|b[dhnorz]|c[ouy]|do|e[cgt]|fj|g[hit]|hk|jm|k[hw]|l[bcy]|m[mtxy]|n[afgip]|om|p[aeghkry]|qa|s[abglv]|t[jrw]|u[ay]|v[cn]))?|d[ejkmz]|e[es]|f[imr]|g[aefglmpry]|h[nrtu]|i[emoqst]|j[eo]|k[giz]|l[aiktuv]|m[degklnsuvw]|n[eloru]|p[lnst]|r[osuw]|s[cehikmnort]|t[dgklmnot]|us|v[gu]|ws)/search\?\K.*'

また、Googleの画像検索やその他の検索サブドメインを含めるには、(www\.)?上記のgrepコマンドのいずれかをに変更する必要があります((www|images|other|sub|domains)\.)?

おすすめ記事