Perlを使用したログの解析

Perlを使用したログの解析

ログを解析するために設計したPerlコマンドを使用したいと思います。これまで私が達成しようとしているのは、特定のタイムスタンプ形式を抽出してホストを検索することです。ログは次のとおりです

2016-05-07T09:07:04.933343+00:00 heroku[router]: status=301 bytes=680 service=2698ms connect=1ms dyno=web.2 fwd="10.29.10.29" at=info host="jamaican.com" request_id=32fc8d88-99f8-4cc2-89f9-284d059eebf8 method=GET path="/blog"

私のコマンドは目的の日付形式を解析できますが、出力にホストを追加する方法がわからないようです。どんな提案でもいいでしょう!

cat test.log  |
perl -lne 'print $1 if  /^([0-9]+[-]+[0-9]+[0-9]+[-]+[0-9]+[0-9]+[T]+[0-9]+[0-9]+[:]+[0-9]+[0-9]+[:]+[0-9]+[0-9])/'

答え1

この試み:

perl -nle'($time, $host) = /^(\S+)\s(?:\S+\s+){8}\S+="(\S+?)"/; print "$time $host"'

出力:

2016-05-07T09:07:04.933343+00:00 jamaican.com
  • \S非空間を表す
  • \sスペースです
  • (?:)キャッチされていない論理的なグループ化です。
  • {8}スキップした「単語」です。
  • \S+="(\S+?)"=意味:2つの引用符の間にある内容までスキップしてキャプチャします。"
  • ($time, $host) = /.../キャプチャされた2つのグループ$time$host

答え2

ホスト名をキャプチャするには、2番目のキャプチャグループを使用する必要があります。

たとえば、サンプル入力を使用すると、次のようになります。

$ cat test.log 
2016-05-07T09:07:04.933343+00:00 heroku[router]: status=301 bytes=680 service=2698ms connect=1ms dyno=web.2 fwd="10.29.10.29" at=info host="jamaican.com" request_id=32fc8d88-99f8-4cc2-89f9-284d059eebf8 method=GET path="/blog"

このperl one-linerはタイムスタンプとホスト名フィールドを抽出します。また、\d各数値に一致回数がある数値の正規表現を一部改善しました。

$ perl -lne 'print "$1 $2" if (m/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d{2}:\d{2}) ([^ ]+) /)' test.log
2016-05-07T09:07:04.933343+00:00 heroku[router]:

別のオプション:

$ perl -lne 'print "$1 $2 $3" if (m/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d{2}:\d{2}) ([^[]+)\[([^]]+)\]/)' test.log
2016-05-07T09:07:04.933343+00:00 heroku router

host="jamaican.com"私はあなたのローカルコンピュータのホスト名が欲しいと仮定します。 (私はログエントリの部分にも気づいていませんでした)。これは望ましくない可能性があるため、ホスト名の後に二重引用符を使用するには、host=次の手順を実行します。

$ perl -lne 'print "$1 $2" if (m/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d{2}:\d{2}).*host="([^"]+)"/)' test.log
2016-05-07T09:07:04.933343+00:00 jamaican.com 

または(より簡単に):

$ perl -lne 'print "$1 $2" if (m/(^\S+).*host="([^"]+)"/)' test.log
2016-05-07T09:07:04.933343+00:00 jamaican.com

またはタイムスタンプを抽出し、.をDate::Parse使用して解析してからDate::Format

$ perl -MDate::Parse -MDate::Format -lne \
  'if (m/(^\S+).*host="([^"]+)"/) {
     print join(" ", time2str("%Y-%m-%d %R %z",str2time($1)), $2)
   }' test.log
2016-05-07 19:07 +1000 jamaican.com

注:タイムスタンプは現地時間帯に変換されます(私の場合は+1000またはオーストラリア東部標準時)。 time2str()デフォルトではローカルタイムゾーンが使用されますが、3番目の引数(time2str(TEMPLATE, TIME [, ZONE]))を指定して別のタイムゾーンの時間を出力することができます。

$ perl -MDate::Parse -MDate::Format -lne   'if (m/(^\S+).*host="([^"]+)"/) {
     print join(" ", time2str("%Y-%m-%d %R %z",str2time($1),"+0"), $2)
   }' test.log
2016-05-07 09:07 +0000 jamaican.com

関連情報