last-modified: 12th/June/'01;
since: 1st/June/2001;
Perl は文字列処理に適した言語です。前節で正規表現を紹介したので、本節では文字列を検索、置換、変換するスクリプトを紹介します。
文字列 string
に正規表現によるパターン pattern
がマッチするかどうか調べるには、次のように記述します;
string =~ /pattern/
input.pl で紹介しました。本節では改めて紹介します。
次のスクリプトは、正規表現と任意の文字列を入力すると、どの部分にパターンマッチしたかを出力するものです。
正規表現の練習にご利用ください。
regexp.pl
>>
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: |
#!/usr/bin/perl
#上の行では、 Perl のパスを記述してください。
while(1) {
print "Regular Expression (x to exit): ";
chomp($pattern = <STDIN>);
last if ($pattern eq 'x');
while(1) {
print "Matched line (x to exit):";
chomp($line = <STDIN>);
last if ($line eq 'x');
if ($line =~ /$pattern/) {
print "Matched string is \"$&\"\n";
} else {
print "failed\n";
}
}
}
|
実行例>>
% perl regexp.pl Regular Expression (x to exit): 時.*分 Matched line (x to exit):今日は9時15分から食事の約束が入っている。 Matched string is "時15分" Matched line (x to exit):明日は11時30分からゼミがある。 Matched string is "時30分" Matched line (x to exit):x % |
正規表現中では、区切り文字もエスケープする必要があります。「 http://www.
」にマッチさせるには、次のように記述する必要があります。
$a =~ /http:\/\/www\./
エスケープ回数を減らすために、正規表現を区切る記号を変更することができます。英数字とアンダースコア( _
)以外の任意の記号に変えられます。
$a =~ m#正規表現# $a =~ m{正規表現} $a =~ m!正規表現! $a =~ m+正規表現+ $a =~ m*正規表現*
但し、区切り文字に採用した記号はメタ文字になりますから、正規表現中ではエスケープする必要があります。次の例は「 begin{document
」を含むかどうか判定します。
$a =~ m{begin\{document}
/正規表現/
は、 m/正規表現/
の省略形です。区切り子がスラッシュ /
に限り、 m
を省略できます。
パターンマッチにはオプションをつけることができます。ここでは三つだけ紹介します。
/正規表現/m /正規表現/s /正規表現/i
上から順番に、「置換対象文字列の改行文字を改行として扱う」、「置換対照の文字列の改行文字を単なる文字として扱う」、「大文字小文字の無視」です。
$a = abc def\nghi jkl | 例文 | 改行文字 \n が含まれる。 |
$a =~ /def$/ | 偽 | 行末が def 。 |
$a =~ /def$/m | 真 | |
$a =~ /a.*l/ | 偽 | a と l の間に任意の文字列。 |
$a =~ /a.*l/s | 真 | |
$a =~ /ABC/ | 偽 | 文字列 ABC 。 |
$a =~ /ABC/i | 真 | |
$a =~ /A*.L/mi | 真 |
m/正規表現/
では文字列を検索していました。次に、パターンにマッチする文字列を置換する書式を紹介します。
$variable =~ s/pattern/replace/
文字列 $variable
から pattern
に一致する部分を探し出し、 replace
に置換します。
変数からパターンを探して置換した結果が、元の変数に代入されなおします。戻り値は、置換回数です。
replace.pl
>>
while(1) { print "ご自由にどうぞ!:"; chomp ($line = <STDIN>); last if $line eq ''; $line =~ s/だ|です/じゃない/; $line =~ s/私/あなた/; print "-> $line\n"; } |
実行例>>
% perl repl.pl ご自由にどうぞ!:私は日本人です。 -> あなたは日本人じゃない。 ご自由にどうぞ!:私は男だ。 -> あなたは男じゃない。 ご自由にどうぞ!:あなたはアメリカ人だ。 -> あなたはアメリカ人じゃない。 ご自由にどうぞ!:私は日本人で、私は男です。 -> あなたは日本人で、私は男じゃない。 ご自由にどうぞ!: % |
最後の例に注目してください。マッチする文字列が複数回登場すると、最初にマッチしたものしか置換されません。これを全て置換するには、オプションをつけます。
置換のオプションはいくつか用意されていますが、ここでは四つだけ紹介します。
s/パターン/置換文字列/g s/パターン/置換文字列/m s/パターン/置換文字列/s s/パターン/置換文字列/i
上から順番に、「マッチするもの全ての置換」、「置換対象文字列の改行文字を改行として扱う置換」、「置換対照の文字列の改行文字を単なる文字として扱う置換」、「大文字小文字の無視」です。
$a = abc def\nabc jkl | 改行文字 \n が含まれる。 |
$a =~ s/abc/xyz/ | xyz def\nabc jkl |
$a =~ s/abc/xyz/g | xyz def\nxyz jkl |
$a =~ s/def$/xyz/m | abc xyz\babc jkl |
$a =~ s/a.*l/xyz/s | xyz |
$a =~ s/ABC/xyz/i | xyz def\nabc jkl |
$a =~ s/ABC/xyz/gi | xyz def\nxyz jkl |
実用的な例としては、文章の表記ゆれの統一や、データの整形が挙げられます。
文末の「だ。」、「である。」を「です。」に変換 | s/だ|である。/です。/g |
Perl, perl, PERL を全て Perl に変換。 | s/perl/Perl/ig |
0120-444-444 を 0120(444)444 に変換。 | s/(\d{4})\-(\d{3})\-(\d{4})/$1\($2\)$3/g |
\d
は半角数字を表す文字集合で、 [0-9]
と等価です。 \d{4}
は半角数字 4 回の繰り返しです。 2 回以上 4 回以下の繰り返しなら \d{2,4}
です。電話番号は一般に \d{2,4}-\d{3,4}-\d{4}
で表現できます。
$1, $2, $3,...
は、パターンマッチしたグループが順に代入されている特殊変数で、後方参照変数と呼びます。この変数を利用した例を紹介しておきます。
s/(菅井)((株)|株式会社)/$2$1/g | 菅井株式会社 、菅井(株) -> (株)菅井 |
s/(\d+)円/\\$1\-/g | 500円 、15000円 など -> \500- , \15000- など |
s/<(br|hr|img|link|input|col|base|meta|area|param)(.*?)>/<$1$2 \/>/g | 空要素の終端を "> " -> " /> " に置換 |
s/<(\/)?([\w]+)/<$1\L$2/g | 要素名を小文字にする。 \L は \E までを小文字にするが、今は指定されていないので、 $2 ([\w]+ ) 全てを小文字にする。\w は英数字で [0-9A-Za-z_] と等価。 |
\
と -
を表現するためにはエスケープする必要があり、それぞれ \\
, \-
と表現しました。
置換でも区切り文字は変更できます。
$a =~ s!パターン!置換文字列! $a =~ s#パターン#置換文字列# $a =~ s{パターン}{置換文字列}
パターンマッチ m/.../
、置換 s/.../.../
を紹介しました。最後に、変換 tr/.../.../
を紹介します。
置換では、文字列を別の文字列に置換していました。変換では、文字を別の文字に変換します。
$variable =~ tr/string/replace/
変数から string
に含まれる全ての文字が、 replace
の中から順番が対応する文字に変換されます。
transfer.pl
>>
$a = abcdefg; print "$a "; $a =~ tr/d-g/1-4/; print "-> $a\n"; |
実行例>>
% perl transfer.pl abcdefg -> abc1234 % |
tr/文字集合/変換文字集合/
において、「文字集合」と「変換文字集合」の個数が対応しない場合は、「変換文字集合の最後の文字」が繰り返されて帳尻が合います。従って、次の二行は同じことです;
$a =~ tr/aogrm/kws/ $a =~ tr/aogrm/kwsss/
文字変換にもオプションがあります。
tr/文字集合/変換文字集合/d tr/文字集合/変換文字集合/c tr/文字集合/変換文字集合/s
上から順番に、「文字集合中の文字で、変換文字集合に無い文字は消す」、「文字集合の補集合」、「変換後に同じ文字が重なったときに一文字に縮める」と云う意味です。
$a = abcdef | |
$a =~ tr/abc/xyz/ | xyzdef |
$a =~ tr/abcd/xy/ | xyyyef |
$a =~ tr/abc/b/d | bdef |
$a =~ tr/abc/z/c | abczzz |
$a =~ tr/ac/b/s | bdef |