古い記事
ランダムジャンプ
新しい記事
ログの処理でよくやるやつを未来の自分のためにメモ。

ファイルリストからファイル中のあるIDが最初に登場したファイルと最後に登場したファイルを得る。つまりは、滞在期間・活動期間を取り出すタスク。

  • 入力
    • ファイルリストを入力とする
    • ファイルは時間順に並べられている
    • ファイルフォーマットはTSV形式で各行の第一カラムをIDとする
  • 出力
    • IDごとに初登場と最終出現のファイル名を出力
    • ファイルリストの最後のファイルに出現している場合は今後も続く可能性があるのでフラグを立てる

■コード (lifespan.pl):
#!/usr/bin/env perl
# -*- coding: utf-8 -*-
use strict;
use warnings;

# ファイルリストを受け取る
my @fns;
while (<>) {
    chomp;
    next if not -e $_;
    push @fns, $_;
}
@fns = sort @fns; # 生成時間(=ファイル名)の順にソート

my %items;
for (my $i = 0; $i < @fns; $i++) {
    open(my $fh, "<", $fns[$i]) or die;
    my %cur;
    while (<$fh>) {
        chomp;
        my ($id, @c) = split(/\t/, $_);
        $items{$id}{first} ||= $fns[$i];
        $items{$id}{last} = $fns[$i];
        $items{$id}{content} = [$id, @c];
        $cur{$id} = 1;
    }
    close($fh);
}

foreach my $id (sort keys %items) {
    my $first = $items{$id}{first}; # 初めてみたとき
    my $last = $items{$id}{last}; # 最後にみたとき
    my $alive = $last eq  $fns[-1] ? 1 : 0; # まだ生きてる?
    print join(" ",
               $id, $alive, $first, $last,
               #@{$items{$id}{content}}
        )."\n";
}

■テストデータと実行例:
% ls -1 log/*
log/20160315.txt
log/20160316.txt
log/20160317.txt
log/20160318.txt
log/20160319.txt
log/20160320.txt
log/20160321.txt

% head log/*.txt
==> log/20160315.txt <==
B0184BHSQU	1250
B012CIAZ34	1260

==> log/20160316.txt <==
B0184BHSQU	1250
B012CIAZ34	599

==> log/20160317.txt <==
B012CIAZ34	648

==> log/20160318.txt <==
B00KMRKDTY	702

==> log/20160319.txt <==
B00KMRKDTY	702

==> log/20160320.txt <==
B00KMRKDTY	702

==> log/20160321.txt <==
B00KMRKDTY	702

% ls log/*.txt |./lifespan.pl
B00KMRKDTY 1 log/20160318.txt log/20160321.txt
B012CIAZ34 0 log/20160315.txt log/20160317.txt
B0184BHSQU 0 log/20160315.txt log/20160316.txt

追記160901: 全面改訂。前の版はウェブ魚拓で。