書式指定した文字列を作成するソースコードは、以下の通りです。
文字列から一番目のタグを取り出す
文字列から指定したパタンのマッチング
サブルーチン(関数)の書き方
サブルーチンの引数の代入。また、関数にファイル名や配列の渡し方
配列の使い方。FIFOとしての使い方(PUSH,POP,初期化(空にする))。配列に配列を追加する
ハッシュ(連想配列)の使い方
ファイル操作。ファイルからの入力、ファイルへの出力。ファイルの削除
-------------------------------------------
#!/usr/bin/perl
use strict; #これを使うと、バグが減る!
my $file=$ARGV[0];
open (IN, $file) or die "$!";
my $tag;
my $tagStart;
my $tagEnd;
my $pattern;
my @header = (); #配列でヘッダー情報を一時保管する
my $headerCount = 0;
my $headerEnd = "<bounds.*\/>";
my $isHeader = 1;
my $minWPTCount = 20;
my $outFileCount = 0;
my $outFileName;
my $outFileNameRoot = "out";
my $currDate = "";
my $prevDate = "";
my @trkptElement = ();
my @trkptElementList = ();
my $elementType = "";
my $countElements = 0;
my $trackPointKey = "trkpt";
my $lon;
my $lat;
my $startTime = "";
my %trkPtRange = ( #ハッシュ配列を使ってトラックの点情報を記録
"latmin" => '0.0',
"latmax" => '0.0',
"lonmin" => '0.0',
"lonmax" => '0.0'
);
my $fo; #出力のファイルハンドらー
sub findKey() #文字列にあるキーワードがあるかどうかをチェックする
{
my $ret = $_[0];
my $key = $_[1];
$ret =~ m/$key/;
}
sub findTag() #XMLのタグを取り出す
{
my $ret = $_[0];
$ret =~ /<(.*?)>/;
$ret = $1;
}
sub getLatLon() #緯度経度を取り出す関数
{
my $ret = $_[0];
my $lon;
my $lat;
$ret =~ /"(.*?)"/;
$lat = $1;
$ret = $'; # ポストマッチの結果を使う
$ret =~ /"(.*?)"/;
$lon = $1;
return ($lat, $lon);
}
sub printElement() #XML要素を引数のファイルハンドらーに出力する
{
my ($fh, $array) = @_; #引数はファイルハンドらーと要素の配列
print $fh @$array;
}
# ここからは mainに相当;入力ファイルにあるすべての行を逐次に処理
while(<IN>) {
my $line = $_;
if ($isHeader == 1)
{
$header[$headerCount] = $line;
$headerCount++;
if ($line =~ /$headerEnd/) {
$isHeader = 0;
$line = $&;
}
} else {
if (&findKey($line, "^<$trackPointKey")) { #文字列のパターンマッチング
($lat, $lon) = &getLatLon($line);
if ($lat > $trkPtRange{"latmax"}) {
$trkPtRange{"latmax"} = $lat;
} elsif ($lat < $trkPtRange{"latmin"}) {
$trkPtRange{"latmin"} = $lat;
}
if ($lon > $trkPtRange{"lonmax"}) {
$trkPtRange{"lonmax"} = $lon;
} elsif ($lon < $trkPtRange{"lonmin"}) {
$trkPtRange{"lonmin"} = $lon;
}
$trkptElement[0] = $line;
$elementType = "$trackPointKey";
$countElements++;
} else {
$tag = &findTag($line);
if ($elementType eq "$trackPointKey") {
if ($tag eq "ele") {
$trkptElement[1] = $line;
} elsif ($tag eq "time") {
$trkptElement[2] = $line;
} elsif ($tag eq "name") {
$trkptElement[3] = $line;
} elsif ($tag eq "cmt") {
$trkptElement[4] = $line;
} elsif ($tag eq "desc") {
$trkptElement[5] = $line;
} elsif ($tag eq "\/$trackPointKey") {
$trkptElement[6] = $line;
push (@trkptElementList,@trkptElement);
}
}
if ($tag eq "time") {
if ($countElements == 1) {
$startTime = $line;
}
$tagStart = "<" . $tag . ">";
$tagEnd = "</" . $tag . ">";
$pattern = $tagStart . ".*" . $tagEnd;
$line =~ /$pattern/;
my $tmp = $&;
$tmp =~ s/$tagStart//g; #get rid of the starting tag
$tmp =~ s/$tagEnd//g; #get rid of the ending tag
my $year = substr($tmp, 0, 4);
my $month = substr($tmp, 5, 2);
my $day = substr($tmp, 8, 2);
my $currDate = $year . "/" . $month . "/" . $day;
if ($prevDate eq "" || $prevDate ne $currDate) {
$outFileName = sprintf("%s%03d.gpx",$outFileNameRoot, $outFileCount);
open($fo, ">$outFileName") or die "$!";
if ($prevDate ne "") {
#分割したファイルの日付と範囲情報をその日のものに設定
$header[7] = $startTime;
$header[8] = "<bounds minlat=\"" . $trkPtRange{"latmin"} . "\" minlon=\"" . $trkPtRange{"lonmin"} . "\" maxlat=\"". $trkPtRange{"latmax"} ."\" maxlon=\"". $trkPtRange{"lonmax"} ."\"\/>";
&printElement($fo, \@header); #output the header
&printElement($fo, \@trkptElementList);
print $fo "</gpx>\n";
close($fo); #ファイルを閉じる
if ($countElements > $minWPTCount) {
#指定点数上のログしか出力しない
$outFileCount++;
}
}
@trkptElementList = ();
$countElements = 0;
}
if ($countElements == 0) {
$trkPtRange{"latmin"} = $lat;
$trkPtRange{"latmax"} = $lat;
$trkPtRange{"lonmin"} = $lon;
$trkPtRange{"lonmax"} = $lon;
}
$prevDate = $currDate;
}
}
}
}
close($fo);
# 最後のファイルには、指定点数以下しかなければ、削除する
if($countElements< $minWPTCount) {
unlink $outFileName;
}
No comments:
Post a Comment