正規表現にマッチした部分の前後の文字列を取り出す
Groovyの正規表現もJavaと同じなので以下で確認
http://java.sun.com/javase/ja/6/docs/ja/api/java/util/regex/Pattern.html#sum
正規表現構文の要約
特殊な構文 (前方参照を行わない)
(?:X) X、前方参照を行わない正規表現グループ
(?idmsux-idmsux) 正規表現ではないが、マッチフラグ i、d、m、s、u、x のオン/オフを切り替える
(?idmsux-idmsux:X) X、前方参照を行わないグループ。指定されたフラグ i、d、m、s、u、x のオン/オフを切り替える
(?=X) X、幅ゼロの肯定先読み
(?!X) X、幅ゼロの否定先読み
(?<=X) X、幅ゼロの肯定後読み
(?X) X、独立した前方参照を行わない正規表現グループ
ニホンゴムズカシイアルネ。。。
幅ゼロの肯定とか幅ゼロの否定ってなんだろう。
マッチしたところの前を取り出す
例
「この先生きのこるには」から「生きのこる」の前を取り出すには
(?=X) 肯定先読みを使えばいいはず
groovy:000> ("この先生きのこるには" =~ /(?=生きのこる)/).each{println it} ===> java.util.regex.Matcher[pattern=(?=生きのこる) region=0,10 lastmatch=]
ん?だめだぞ。
なんで?
先読み、後読みは何に使うのかというと、「文字列の前と後にどんな文字が来るか判別したくて、
なおかつその部分にはマッチさせたくない」という場合に使う。
たとえば、「hoge(?=pattern)」は patternが後ろにあるhogeにマッチするが、
(?=pattern)部分にはマッチしない。
「(?<=pattern)hoge」は patternが前にあるhogeにマッチするが、(?<=pattern) 部分には
マッチしない。
(?=X) 前方先読みをしてXとマッチ※1
(?!X) 前方先読みをしてXとノンマッチ(==前方にXがない)
(?<=X) 後方振り返り読みをしてXとマッチ
(?X) Xを捕捉グループではない独立的グループと見なす
(所有的・支配的マッチを行なう※2)〔訳注※1:これら4つの、前方先読みと後方振り返り読みマッチにマッチした部分は、
マッチ本体に含まれないため、ゼロ幅(zero width)マッチと呼ばれる。
たとえばY(?=X)は、前方にXがあるYという意味であり、拾われるマッチ本体はYと
マッチした部分のみです。京都(?=府)は、“京都府”という語句の中の“京都”とマッチします。
京都市の京都とはマッチしません。〕
なるほど、そう言うことか。
(?=X)じゃだめで、hoge(?=X)みたいに使うのね。
groovy:000> ("この先生きのこるには" =~ /.*(?=生きのこる)/).each{println it} この先 ===> java.util.regex.Matcher[pattern=.*(?=生きのこる) region=0,10 lastmatch=]
OK!!
マッチしたところの後ろを取り出す
例
「この先生きのこるには」から「生きのこる」の後を取り出す
後ろを取り出すのも同じ。(?<=X)じゃだめで、(?<=X)hogeみたいに使う。
groovy:000> ("この先生きのこるには" =~ /(?<=生きのこる)/).each{println it} ===> java.util.regex.Matcher[pattern=(?<=生きのこる) region=0,10 lastmatch=]
groovy:000> ("この先生きのこるには" =~ /(?<=生きのこる).*/).each{println it} には ===> java.util.regex.Matcher[pattern=(?<=生きのこる).* region=0,10 lastmatch=]
実行環境
- OS:Windows XP
- Groovy Version: 1.6.5
- JVM: 1.6.0_12
Groovyの詳細についてはJavadocと以下の書籍を参考にしている。
ページ番号は、この書籍のページ番号
問題自体は以下の書籍のもの。rubyと似てる部分も多いので、ヒントにもなる。
写経でもいいが自分で考えるために他言語の例をGroovyで置き換えてる。
Groovyイン・アクションを読むならあった方が便利かな。