置換s///(第8章「もっと正規表現」続き)
今までは主に正規表現での検索についてやってきたけど、今回は検索した結果を置き換える置換s///に関して。
簡単な置換
置換には「s///」という機能(これは演算子?手続き?関数?構文????)を使うそうな。
次のようなスクリプトを実行すると、
my $str = "How I wonder what you are.\n"; $str ~= s/what/who/; print $str;
以下のように表示される。http://ideone.com/ve8RB
How I wonder who you are.
正規表現を表すときは2個スラッシュで囲んだけど、
m/foo/
みたいなm//を使った書き方ができた。それに似てて置換の場合は、
s/foo/bar/
って書いて、正規表現を1個目と2個目のスラッシュで囲まれた部分で指定して、置換後の文字列を2個目と3個目のスラッシュで囲まれた部分で指定する。
特殊変数$&を使って置換
上記の簡単な例のように、置換後を固定で書くと柔軟さに欠ける。すでに 第7章「正規表現の基本」 - チキン煮込みチーズミックス4辛 で出てきた特殊変数$&を使うと、マッチした部分の文字列をとってこれるのでなんか便利そう。
特定の語句を探して、それを一重引用符で囲む例
my $str = "How I wonder what you are.\n"; $str =~ s/what/'$&'/; print $str;
特定の語句を探して、それを増殖させる例
my $str = "How I wonder what you are.\n"; $str =~ s/who|when|where|what|why|how/$& $& $&/gi; print $str;
正規表現で検索して削除
置換後の文字列を空白にしてやればOK
my $str = "How I wonder what you are.\n"; $str =~ s/w\w+//g; print $str;
上記のスクリプトでwで始まる単語(wonderとwhat)を消せたけど、余計なスペースが残った。http://ideone.com/9BZkL
そんな時は「スペース0個以上」も正規表現に含めてやるといい。http://ideone.com/PGrvy
my $str = "How I wonder what you are.\n"; $str =~ s/w\w+ *//g; print $str;
特殊変数$1、$2、$3、...の利用
これもすでに出てきたけど、使えるそうだ。
my $str = "The price is 300yen. The distance is 120km.\n"; $str =~ s/((\d+)([A-Za-z]+))/$2<$3>/g; print $str;
単位である「yen」と「km」を括弧で囲んでみた http://ideone.com/JRSbA
my $str = "How I wonder what you are.\n"; $str =~ s/(\w+) (\w+)\./$2 $1!/g; print $str;
単位である文末の2語を入れ替えてビックリマークを付け加えてみた http://ideone.com/Dcphl
式を評価する修飾子/e
修飾子/eを使うと、置換後の部分をPerlの式として評価してくれるらしい。
my $str = "The price is 300yen. The distance is 120km.\n"; $str =~ s/(\d+)/$&*2/eg; print $str;
数値を2倍してみたhttp://ideone.com/VXcBR
my $str = "The price is 300yen. The distance is 120km.\n"; $str =~ s/(\d+)/$&/eg; print $str;
上記のような場合だと、修飾子/eがあってもなくても同じ結果だけど、じゃあ「評価」って何なんだろう?
修飾子/eあり:http://ideone.com/71JqQ 修飾子/eなし:http://ideone.com/yLj2N
関数の定義方法はまだやってないけど、関数が使えると出来ることがぐっと広がりそう。
メタ文字\b
"and" を "AND" に置換したかったけどミスった例。http://ideone.com/1RTav
my $str = "Loves plum cake and sugar candy.\n"; $str =~ s/and/AND/g; print $str;
こういうときはメタ文字\bで、単語の境界を明示してやればOK。http://ideone.com/C6b2C
my $str = "Loves plum cake and sugar candy.\n"; $str =~ s/\band\b/AND/g; print $str;
\bは
- \wと\W
- \Wと\w
の間にマッチするそうだ。
修飾子
1行として扱う/s
メタ文字.は改行文字\nにマッチしないけど、修飾子/sをつけるとマッチするようになる。http://ideone.com/XZbri
my $str = "abc123\ndef456123xdef"; if ($str =~ /123.def/s) { print "$&\n"; }
修飾子/sをつけない場合は http://ideone.com/Q6YEa
複数行として扱う/m
修飾子/mを使うと、改行を区切り文字とした複数行としてパターンマッチできる。http://ideone.com/9eG1C
my $str = "point123\npoint456\npoint789.\npoint012"; while ($str =~ /\d+$/mg) { print "$&\n"; }