文字列を検索する

実行環境

ソースと結果

パターンが含まれるかどうかを調べる

ソース

println "パターンが含まれるかどうかを調べる"

("a c"=~/[ \t]/).find()
("abc"=~/[ \t]/).find()
(~/[ \t]/).matcher("a c").find()
 (~/[ \t]/).matcher("abc").find()

結果

パターンが含まれるかどうかを調べる
===> null
===> true
===> false
===> true
===> false

↑これが正解。Matcher#find()の復帰値はboolean。
(str=~pattern)と(~pattern).matcher(str)が同じ。

ソース

println "   全体一致なのでNG"
("a c"==~/[ \t]/)
("abc"==~/[ \t]/)
"a c".matches(/[ \t]/)
"abc".matches(/[ \t]/)
("a c"=~/[ \t]/).matches()
("abc"=~/[ \t]/).matches()

結果

   全体一致なのでNG
===> null
===> false
===> false
===> null
===> false
===> false
===> false
===> false

↑==~の場合は完全一致、Matcher#mathes()も完全一致。そのためfalseになる。
=~は部分一致。


ソース

println "   左辺と右辺が逆なのでNG"
(/[ \t]/==~"a c")
(/[ \t]/==~"abc")

(/[ \t]/=~"a c").find()
(/[ \t]/=~"abc").find()

結果

   左辺と右辺が逆なのでNG
===> null
===> false
===> false
===> false
===> false

正規表現のパターンと検索対象の文字列が逆
Rubyの人だとこう書きそう。だけど逆なんだよね。
なんで中途半端にまねたんだろ。

ソース

println "   Matcherオブジェクトが返されるのでNG"
("a c"=~/[ \t]/)
("abc"=~/[ \t]/)

結果

   Matcherオブジェクトが返されるのでNG
===> null
===> java.util.regex.Matcher[pattern=[ \t] region=0,3 lastmatch=]
===> java.util.regex.Matcher[pattern=[ \t] region=0,3 lastmatch=]


ソース

println "   マッチした文字列が返されるのでNG"
"a c".find(/[ \t]/)
"abc".find(/[ \t]/)

結果

   マッチした文字列が返されるのでNG
===> null
===>
===> null

↑String#find(Pattern pattern) は文字列が返されるため。

パターンが出現するバイト位置を調べる

ソース

println "パターンが最初に出現するバイト位置を調べる"
"xxxabcabcabcxxx".indexOf("abc")
"xxxabcabcabcxxx".indexOf(".")
"xxx..........xxx".indexOf(".")

println "パターンが最後に出現するバイト位置を調べる"
"xxxabcabcabcxxx".lastIndexOf("abc")
"xxxabcabcabcxxx".lastIndexOf(".")
"xxx..........xxx".lastIndexOf(".")

結果

パターンが最初に出現するバイト位置を調べる
===> null
===> 3
===> -1
===> 3
パターンが最後に出現するバイト位置を調べる
===> null
===> 9
===> -1
===> 12

↑出現しない場合は-1になる。

マッチの詳しい情報を得る

ソース

println "マッチの詳しい情報を得る"

str = "xxxabcabcabcxxx"
pattern = /abc/
m = (str=~pattern)
m.find()
m.start()
m.end()
m[0]
str.substring( m.start(), str.length() )

m2 = (~pattern).matcher(str)
m2.find()
m2.start()
m2.end()
m2[0]
str.substring( m2.start(), str.length() )

結果

マッチの詳しい情報を得る
===> null
===> xxxabcabcabcxxx
===> abc
===> java.util.regex.Matcher[pattern=abc region=0,15 lastmatch=]
===> true
===> 3
===> 6
===> abc
===> abcabcabcxxx
===> java.util.regex.Matcher[pattern=abc region=0,15 lastmatch=]
===> true
===> 3
===> 6
===> abc
===> abcabcabcxxx

↑最後のRubyのpost_match相当がもっと簡単にできないだろうか?

1つもの文字列中のすべての候補にマッチさせる

ソース

println "1つの文字列中のすべての候補にマッチさせる"
str2 = "あ\n aadかきe\ne さ0\n0aた\n iiな\n"
m3 = (~/[あ-ん]+/).matcher(str2)
m3.find()
m3.each {println it}

結果

1つの文字列中のすべての候補にマッチさせる
===> null
===> あ
 aadかきe
e さ0
0aた
 iiな

===> java.util.regex.Matcher[pattern=[あ-ん]+ region=0,24 lastmatch=]
===> true
あ
かき
さ
た
な
===> java.util.regex.Matcher[pattern=[あ-ん]+ region=0,24 lastmatch=]

↑each該当するもの分ループさせる。

パターンを含む行のみを処理する

ソース

println "パターンを含む行のみを処理する"

str2.findAll(~/.*[あた].*/) { println it}
str2.findAll(~/.*[あた].*/) { line->println line}

println "NG" 
str2.findAll(~/[あた]/) { line->println line}

結果
>|groovy|
パターンを含む行のみを処理する
===> null
あ
0aた
===> [null, null]
あ
0aた
===> [null, null]
NG
===> null
あ
た
===> [null, null]

↑findAllだと該当の文字列になるので/[あた]/だとだめ。