Snippets

sironekotoro NHKの首相動静 自称CSVファイルをPerlでパースしようとするも、元のファイルが間違ってるので出力も間違ってるという悲しいオチ

Created by sironekotoro
use strict;
use warnings;
use feature qw/say/;

use utf8;
use Encode qw(encode_utf8);
use Time::Piece;

# 処理するファイルを指定。同じフォルダに置く。
my $file = '201808.csv';

# ファイルの改行を全部削り、1行にしてスカラ変数に読み込む
my $str;
open my $FH, '<:encoding(utf16le)', $file;
for my $line (<$FH>) {
    $line =~ s/\r+//g;
    $line =~ s/\n+//g;
    $str .= $line;
}
close $FH;

# 1エントリ(1動静?)に1つしかない日付に
# BOL(Before of Line)という文字列をくっつけて
# 区切り文字の目印にする
$str =~ s|(\d+/\d+)|BOL$1|g;

# BOLという文字で分割する
my @array = split /BOL/, $str;

my @dousei;
for my $entry (@array) {

    # CSVとか言いつつタブ区切りなのでタブで分割する
    my ( $date, $time, $text ) = split /\t/, $entry;

    # 空の行は飛ばす
    next unless ( defined $date && defined $time && defined $text );

    # ファイル名から年(先頭から4桁の数字)を取り出す
    $file =~ /\A(\d{4})/;
    my $year = $1;

    # びっくりすることに、CSVファイルの日付が信用できない
    # 日が信用できないパターン
    # https://twitter.com/sironekotoro/status/1033613225303003136
    # 月が信用できないパターン
    # https://twitter.com/sironekotoro/status/1033665694682951680

    # 時刻が終日のパターンがある
    # 201807.csv
    # 7/28  (終日)    終日、来客はなく、東京・富ヶ谷の私邸で過ごす
    # 置換使って 00:00:00 に置き換える

    if ($time =~ /(終日)/){
        $time = '00:00:00';
    };

    # 日付と時間を元にエポック秒に変換する
    my $t = Time::Piece->strptime( "$year $date $time", '%Y %m/%e %H:%M' );

    # 配列にハッシュリファレンスを追加する
    push @dousei, { epoch => $t->epoch, text => $text };

}

# 配列の中のハッシュリファレンス中のエポック秒を元にソートする
@dousei = sort { $a->{epoch} <=> $b->{epoch} } @douseia;

# 表示する
for my $e (@dousei) {
    my $t = Time::Piece->strptime( $e->{epoch}, '%s' );
    say $t->ymd, "\t", $t->hms, "\t", encode_utf8( $e->{text} );
}

Comments (0)