0
0

More than 5 years have passed since last update.

2文字以上の空白で区切られた固定長テキストの解析

Posted at

概要

コマンド出力等にありがちな、以下の条件の固定長テキストを解析するためのサブルーチン。

  • 全体としては固定長テキスト
  • 先頭はヘッダ行
  • カラムは実行ごとに異なる(例えばコマンド実行時の引数で変わる)
  • カラムの幅は実行ごとに異なる(例えば出力されるデータにあわせて変わる)
  • カラムの間は2文字の空白で区切られている
  • レコードによっては、あるカラムが空のこともある

解析方法

以下の方針で解析します。

  • 1行目をヘッダ行として処理します。
  • ヘッダ行の「2文字以上の空白」の出現場所から、各フィールドの長さを判断します。
  • 残りの行を、固定長テキストとして解析します。
  • 結果は、ハッシュリファレンスの配列の形で返します。

ヘッダ行から「固定長」の長さを取得するので、事前に各フィールドの長さを定義する必要がなくなります。レコード行には、空のフィールドや、2文字以上の空白を含むフィールドがあっても大丈夫です。

サブルーチン

sub parse_multispaces_separated {
    my $text   = shift;
    my @rows   = ();

    # split each lines
    my @lines  = grep { /\S/ } split(/\n/, $text);
    my @length = map { length($_) } ($lines[0] =~ /(\S(?: ?\S)* {2,})/g);
    foreach my $line (@lines) {
        my @values = map { substr($line, 0, $_, '') } @length;
        push(@values, $line);
        s/^\s+|\s+$//g foreach (@values);
        push(@rows, \@values);
    }

    # get column names and hash-nize
    my @columns = @{shift(@rows)};
    foreach my $row (@rows) {
        my @values = @{ $row };
        my %hash = map { $columns[$_] => $values[$_] } (0..$#values);
        $row = \%hash;
    }

    return @rows;
}

使用例

my $text = <<EOF;
Customer Name   Location       email
Akai Isao       Tokyo, Japan   akai@example.com
Uda Eijiro      Osaka, Japan   eijiro.uda@example.com
Oswald Kahn     Aidaho, U.S.   kahn-oswald@oswald-inc.example.com
Silvia Tolen                   silvia@example.com
EOF

my @rows = &parse_multispaces_separated($text);

use Data::Dumper;
print Dumper(\@rows);

sub parse_multispaces_separated {
    (略)
}

使用例の出力

$VAR1 = [
    {
        'email' => 'akai@example.com',
        'Location' => 'Tokyo, Japan',
        'Customer Name' => 'Akai Isao'
    },
    {
        'email' => 'eijiro.uda@example.com',
        'Location' => 'Osaka, Japan',
        'Customer Name' => 'Uda Eijiro'
    },
    {
        'email' => 'kahn-oswald@oswald-inc.example.com',
        'Location' => 'Aidaho, U.S.',
        'Customer Name' => 'Oswald Kahn'
    },
    {
        'email' => 'silvia@example.com',
        'Location' => '',
        'Customer Name' => 'Silvia Tolen'
    }
];
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0