Ando Computer Behavior R&D
Perl tips -- リスト/抽出関係の処理
- リストの操作
- コンマで区切る(split)
- コンマの数を数える
- csvファイルからセルを抽出する(セル内改行対策済み)
- \"の付いた"に囲まれた文章を抽出する
- ソートする
リストの操作
まぁこんな感じです。
push,pop,shift,unsiftくらいは使えるようになった方が、
ってこれもよく書き方忘れるんだよなぁ…
#!/usr/bin/perl
@data = ("aaa","bbb","ccc","ddd");
print "#最初の状態\r\n";
&print(@data);
#
print "#一個左シフトする\r\n";
($dummy,@data) = @data;
&print(@data);
#
print "#1個右に積む\r\n";
@data = (@data,"migi-tumu");
&print(@data);
#
print "#1個左に積む\r\n";
@data = ("hidari-tumu",@data);
&print(@data);
#
print "#push 1個右に積む\r\n";
push(@data,"e");
&print(@data);
#
print "#pop 1個右から抜く\r\n";
$dummy = pop(@data);
&print(@data);
#
print "#shift 1個左から抜く\r\n";
shift(@data);
&print(@data);
#
print "#unshift 1こ左から積む\r\n";
unshift(@data,"unshift");
&print(@data);
#
#状態を表示する
sub print {
local(@data) = @_;
foreach (@data) {
print " : " . $_;
}
print "\r\n";
}
以下は結果です。
#最初の状態
: aaa : bbb : ccc : ddd
#一個左シフトする
: bbb : ccc : ddd
#1個右に積む
: bbb : ccc : ddd : migi-tumu
#1個左に積む
: hidari-tumu : bbb : ccc : ddd : migi-tumu
#push 1個右に積む
: hidari-tumu : bbb : ccc : ddd : migi-tumu : e
#pop 1個右から抜く
: hidari-tumu : bbb : ccc : ddd : migi-tumu
#shift 1個左から抜く
: bbb : ccc : ddd : migi-tumu
#unshift 1こ左から積む
: unshift : bbb : ccc : ddd : migi-tumu
コンマで区切る(split)
split()で区切ります。
これも正規表現が引数1個目か2個目かとか、
よく忘れているんですよねー。
#!/usr/bin/perl
$data = "abc,def,ghi";
@splitData = split(/,/,$data);
foreach(@splitData) {
print "data: " . $_ . "\r\n";
}
#
コンマの数を数える
ときどきやりたくなるやつです。
#!/usr/bin/perl
$data = "abc,def,ghi";
$counter = 0;
while($data =~ s/,//) {$counter++;}
print ",の数は=" . $counter;
#
csvファイルからセルを抽出する(セル内改行対策済み)
Excelから抽出できるカンマ区切りファイル(*.csvファイル)は、
セルの中に改行があったり、セル内に「,(カンマ)」があったりすると
単純にsplit()することができません。
対策をするには以下のようにします。
#!/usr/bin/perl
open(IN,$ARGV[0]) || die "(arg0:" . $ARGV[0] . ")$!";
@data = <IN>;
@data = commaSplit(@data);
foreach(@data) {
@targetData = split(/,/,$_);
$i=0;
foreach(@targetData) {
print $i . ":" . $_ . "\r\n";
$i++;
}
}
# カンマ区切り分を抽出する( ”対策)
sub commaSplit {
local(@a) = @_;
local(@b) = ();
local(@targetData) = ();
local($data,$flag);
$data = "";
$flag = 0;
foreach (@a) {
@b = split(/,/,$_);
foreach (@b) {
if ($flag == 0) {
$data = $data . "," . $_;
} else {
$data = $data . ";" . $_; # 囲まれている
}
$flag = &getDouble($_,$flag);
#print OUT $data . "\n";
}
if ($flag == 0) { # 囲まれなくなった
$data =~ s/\"//g;
$data =~ s/\'//g;
$data =~ s/\s+//g; # 最後の改行を吹き飛ばす
$data =~ s/^,//g; # 先頭の,はいらない
@targetData = (@targetData,$data);
$data = "";
}
}
return(@targetData);
}
# ”の数を数える
sub getDouble {
local($_,$flag) = @_;
local($counter);
$counter = 0;
$counter++ while /\"/g;
#print OUT "aa " . $counter . " ($_)\r\n";
$flag = ($flag + $counter) % 2;
return $flag;
}
#
\"の付いた"に囲まれた文章を抽出する
"で囲まれた文章を抽出するには、
単純に/\"[\"]*\"でも良いのですが、
文章内に"があるとうまく動作しません。
正規表現がかなりややこしいですが、
以下のような感じにすれば通ります。
#!/usr/bin/perl
#
$_ = 'print "(\")こんなのとか(\\\")こんなのが入った文章はいやだ\r\n";';
#
if (/\"((\\[rn\"]|[^\"])+)\"/) {
print "hit : " . $1 ."\r\n";
} else {
print "no hit :" . $_ ."\r\n";
}
#
ソートする
ソートするにはsort()、
反転するにはreverse()を使います。
ただし、これだと単純にアスキーキャラでソートしてしまうので、
数字でソートするとかはできません。
#!/usr/bin/perl
#
@data = ("34" , "dre" , "54d" , "aee");
@data = sort @data;
@data = reverse @data;
&print(@data);
exit(0);
#
#状態を表示する
sub print {
local(@data) = @_;
foreach (@data) {
print " : " . $_;
}
print "\r\n";
}
#
数字のソートといったことを行うためには、
処理用の関数を作ることで対応します。
#!/usr/bin/perl
#
@data = ("34" , "23" , "1" , "115");
@data = sort number @data;
&print(@data);
exit(0);
#
#番号順に並び変える
sub number {
if ($a < $b) {
return -1;
} elsif ($a == $b) {
return 0;
} elsif ($a > $b) {
return 1;
}
}
#
#状態を表示する
sub print {
local(@data) = @_;
foreach (@data) {
print " : " . $_;
}
print "\r\n";
}
#