Perlを業務で扱って1年程なので、拙い記事になりますが、お手柔らかに。。。
経緯
現場でiniファイル型(1レコード複数行)ファイルを扱ったときに、kshコマンドで1レコード1行に変換するのが面倒だったので、Perlで処理したときのメモ。
ただし、誰も保守できないとのことで没になったが、今度自分が使う際のメモ程度に記載しておく。
使用した項目
- Perlの入力行セパレータ
Perlでは、行を定義する際のセパレータとして、デフォルトの変数"$/"に改行文字が設定されている。1レコード複数行のデータを扱う際は、この変数を操作することで複数行を1レコードとして扱うことができる。
- パターンマッチの複数行モード
パターンマッチ演算子の"m"を使うことにより、パターンマッチで複数行モードで行うことできる。
実際のサンプル
- テキストサンプル
以下のようなiniファイル形式のテキストファイルを扱った。
sample.txt
#
# ID=HOGE1
#
ID=HOGE1
FILE=/HOGE/TO/PATH1.txt
GRP=FUGA1
END
#
# ID=HOGE2
#
ID=HOGE2
FILE=/HOGE/TO/PATH2.txt
GRP=FUGA2
END
#
# ID=HOGE
#
ID=HOGE3
FILE=/HOGE/TO/PATH3.txt
GRP=FUGA3
END
- Perlコード
sample.pl
#! /usr/bin/perl
use strict;
use warnings;
# 引数を変数に格納
my $argument = $ARGV[0];
# 既存セパレータの退避(オプション)と新規セパレータの設定
my $oldsep = $/;
$/ = "END";
# ファイルを開き、複数行モードで処理
open my $fh,"<",$argument;
while(<$fh>){
# 空行だけの行をスキップする
next if /^\n$/;
# 改行を[,]に変換する
$_ =~ s/\n/,/mg;
# [,END]を削除する
$_ =~ s/\,END//mg;
# ヘッダー部分の削除
$_ =~ s/^\,{0,2}\#.+\,{2}//mg;
# ハッシュへ一括変換
my %foo = split(/[=,]/,$_);
while(my($key,$val) = each %foo){
print "[key]:$key,[val]:$val\n";
}
}
# ファイルを閉じる
close($fh);
# 既存セパレータに戻す
$/ = $oldsep;
結果
当たり前のようだが以下のような結果になった。
$ ./untitled.pl ./test.txt
"key":FILE,"val":/HOGE/TO/PATH1.txt
"key":GRP,"val":FUGA1
"key":ID,"val":HOGE1
"key":FILE,"val":/HOGE/TO/PATH2.txt
"key":GRP,"val":FUGA2
"key":ID,"val":HOGE2
"key":GRP,"val":FUGA3
"key":ID,"val":HOGE3
"key":FILE,"val":/HOGE/TO/PATH3.txt
$
もう少し正規表現の部分をスマートにできればもう少し綺麗なコードになるかも。。。
むしろワンライナーでいけるな、これ。。。