web-dev-qa-db-ja.com

日付でログファイルを分割する

次のログ形式のログファイルがあります。

###<Aug 8, 2016 11:59:05 PM>
different text
...
different text
###<Aug 15, 2016 9:10:55 AM>
different text
...
...
...
different text
###<Aug 22, 2016 10:02:17 PM>
different text
...
...
...
...
different text
###<Sep 1, 2016 1:00:01 AM>
different text
###<Sep 7, 2016 3:00:01 PM>
different text
...
...
different text

このログファイルを日付ごとにYYYY_MM_DD.logファイルに分割するにはどうすればよいですか?

7
tm4ig

Perlソリューション。GNU dateを利用して日付を変換します。

Perl -ne 'if(/^###<(.*)>/){
            chomp($d=`date -d \"$1\" +%Y_%m_%d`);
            $name="$d.log"
          } 
          open(my $fh,">>","$name"); 
          print $fh $_;' file.log 

説明

  • -ne:入力ファイルを1行ずつ読み取り(各行を特殊変数$_として保存)、-eで指定されたスクリプトを各行に適用します。
  • if(/^###<(.*)>/):行が###<で始まる場合、<>の間のすべてを$1としてキャプチャします(かっこがすることです)。
  • chomp($d=date -d\"$ 1 \" +%Y_%m_%d);dateコマンドは日付を再フォーマットします。例えば:

    $ date -d "Sep 1, 2016 1:00:01 AM" +%Y_%m_%d
    2016_09_01
    

    chompは、dateの結果から最後の改行を削除するため、後で使用できます。

  • $name="$d.log"dateコマンドの結果と.logを変数$nameとして保存します。
  • open(my $fh,">>","$name");:ファイルハンドル$nameとしてファイル$fhを開きます。ファイルハンドルが何であるかわからなくても心配する必要はありません。これは、print $fh "foo"foo$nameに出力することを意味します。
  • print $fh $_;:ファイルハンドル$fhが指すファイルに現在の行を出力します。したがって、$nameとして現在保存されているものに行を印刷します。
7
terdon

これを解決する1つの方法は、awkを使用することです。たとえば、次のコマンド:

awk -F'[ <,]+' '/^###/{close(f);f=$4"_"$2"_"$3".log"}{print >> f}END{close(f)}' file

日付フィールドをファイル名として使用して、ファイルをファイルに分割する必要があります

6
user000001

awkの場合:

awk '/^#+<[^>]+>$/ {if (lines) print lines >file; \
     dt=gensub("^#+<([^>]+)>$", "\\1", $0)
     dt_cmd="date -d \""dt"\" +%Y_%m_%d.log" \
     dt_cmd | getline file; lines=$0; next}; \
     {lines=lines ORS $0} END {print lines >file}' file.log

読み取り可能なフォーム:

awk '
      /^#+<[^>]+>$/ {
                    if (lines) 
                        print lines >file
                    dt=gensub("^#+<([^>]+)>$", "\\1", $0)
                    dt_cmd="date -d \""dt"\" +%Y_%m_%d.log"
                    dt_cmd | getline file; lines=$0
                    next
                    }
      {
      lines=lines ORS $0
      } 
      END {
          print lines >file
          }' file.log
  • /^#+<[^>]+>$/は日付を含む行と一致します。{}で囲まれたチャンクは、条件が一致した場合にのみ実行されます。一致する場合、外部dateコマンドを使用して出力を変数fileに保存し、変数linesの内容をファイルfile(前のチャンクから)、変数linesを次の行で再度インスタンス化します

  • 他のすべての行については、行を変数linesとして連結します

  • 最後のチャンクは、ENDブロックに入れることで保存されます

6
heemayl