TopProgramming LanguagePerl正規表現 > 2013年7月
2013年7月30日

Perlの正規表現で繰り返し置換する方法

July 30,2013 12:55 AM
Tag:[]
Permalink

Perlの正規表現を使って文字列を繰り返し置換する方法を紹介します。

テキストの中のある文字列を一律変換するのではなく、マッチする文字列の一部を除外しなければいけないという条件つきです。

ネットで色々調べてみましたが、同じ解決策がみつけられなかったので自力で作ってみました。

1.問題点

次のように、右辺に含まれる「0」だけを「A」に変換する必要が生じました。

変更前

102030=012301230123

変更後

102030=A123A123A123

「=」以外の、左辺および右辺の文字数や「0」の出現位置は不定とします。

実際には1行ではなく、このような行が数十行にわたって記述されていますが、1行単位で処理すればいいのでここでは省略しています。

ちなみにネットで調べたところ、次のようなサンプルは数多くヒットしました。

例:テキストに含まれる「0」をすべて「A」に変更

変更前

012301230123

変更後

A123A123A123

この例であれば、次のような一括置換を行えば一撃です。

my $content = '012301230123';
$content =~ s/0/A/g;

が、この方法を使って

my $content = '102030=012301230123';
$content =~ s/0/A/g;

とすると、左辺も含めてすべての「0」が「A」に変換されてしまいます。

変更前

102030=012301230123

変更後

1A2A3A=A123A123A123

2.特定の文字列を複数回置換する

追記:@usualomaさんから回答いただきました。ありがとうございました!

「(?!式)」は、後続の文字列が式に一致しなければマッチする拡張構文です。

この場合、後続の文字列が「=」に一致しない「0」に(複数回)マッチするということになります。勉強になりました。

以降は元エントリーの内容ですがそのまま残しておきます。

「=」で文字列を分割して右辺を一括置換した後結合するという方法もありますが、ここではwhileと組み合わせて実現してみました。

my $content = '102030=012301230123';
while ( $content=~ s/(.*=)(.*)0(.*)/$1$2A$3/ ) {}

これで変換後の値は、右辺のすべての「0」が「A」に変換されて、

102030=A123A123A123

となります。

このコードではまず最後尾の「0」を「A」に変換し、while文を使って左方向に向かって右辺のすべての「0」を「A」に変換していきます。

3.その他

ちなみにg修飾子を使って、

$content =~ s/(.*=)(.*)0(.*)/$1$2A$3/g;

でよいのでは?と思った方もいるかもしれませんが、上のコードでは最後に出現した「0」だけが「A」に置換されて、

102030=01230123A123

となってしまいます。

また、最短マッチを意味する「量指定子+?」を使った、

$content =~ s/(.*=)(.*?)0(.*)/$1$2A$3/g;

の場合は、最初に出現した「0」しか「A」に置換されません。

102030=A12301230123

ということで2項のようなコードにしています。

よりエレガントな解があると思いますので、質問の意味も含めてエントリーしてみました。

Comments [0] | Trackbacks [0]
Now loading...
Recent Entries
ギターに入った猫
掲載広告募集
Styles
Font Size
Default
For defective color vision
Gray Scale
RGB Color
Search this site

このブログをメールで購読する by:FeedBurner

AMN
Categories
Monthly Archives
2021年
2020年
2019年
2018年
2017年
2016年
2015年
2014年
2013年
2012年
2011年
2010年
2009年
2008年
2007年
2006年
2005年
2004年
2003年
BlogPeople
Syndicate this site
FeedBurner(RSS1.0/RSS2.0/Atom)
Counter
これまでのアクセス
Powered by
Movable Type 6.0.3