以前試したように Haskell において正規表現を使いたい場合は、Text.Regex モジュールを利用する。(cf. Haskell で正規表現)
流れとしては、
- 「正規表現型の値」を生成 : mkRegex
- (1) を利用して一致する部分があるか確かめる : matchRegex
import Text.Regex main = do print $ matchRegex (mkRegex "(piyo)") "123hogepiyofuga" print $ matchRegexAll (mkRegex "(piyo)") "123hogepiyofuga"
結果は、
Just ["piyo"] Just ("123hoge","piyo","fuga",["piyo"])
ただし、matchRegex において Just で包んで返される値は、 mkRegex の正規表現で subexpression として指定 したもの。
Python と比較
Python でも同様の手順を踏む。
- compile
- match または search (cf. 4.2.2 マッチング vs 検索)
import re print re.compile("piyo").match("123hogepiyofuga") print re.compile("piyo").search("123hogepiyofuga")
結果、
None <_sre.SRE_Match object at 0x025F6598>
search と match の違い
4.2.3 モジュール コンテンツ によると、
search(pattern, string[, flags])
string全体を走査して、…
match(pattern, string[, flags])
もし string の先頭で0 個以上の文字が正規表現 pattern と マッチすれば、…
Haskell の matchRegex は search に相当するということかな。
compile なし
上記は正規表現を使い回さないのであれば、compile せずに、
print re.match("piyo", "123hogepiyofuga") print re.search("piyo","123hogepiyofuga")
matchRegexAll のように
Haskell の matchRegexAll と同じものを取得するには、4.2.5 MatchObject オブジェクト を使い、
str = "123hogepiyofuga" m = re.search("(piyo)",str) print str[:m.start()], m.group(1), str[m.end():], m.groups()
結果は、
123hoge piyo fuga ('piyo',)
Ruby と比較
Ruby で正規表現と言えばすぐに /正規表現/=~ “文字列” を思い出す。(cf. Regexp - Rubyリファレンスマニュアル) そういう書き方ができるから、テキスト処理をするとき Ruby は扱いやすいなぁ~と思った。組み込み変数 は忘れてしまうけれど。 ^^;
p /(piyo)/ =~ "123hogepiyofuga" p $`, $1, $', $~.to_a
結果、
7 "123hoge" "piyo" "fuga" ["piyo", "piyo"]
せっかくなので、上記の組み込み変数だけでも覚えておこう。
-
`~’
Python でも =~ が使えるといいのに…。 (+_+)
Haskell でも =~
Text.Regex.Posix.Wrap
前回、A Haskell regular expression tutorial を読むのを見逃してた。(via Cookbook - HaskellWiki) Haskell でも Ruby と同じように =~ が使えるようだ。
定義されている場所は、Text.Regex の一つ下の階層に Text.Regex.Posix があり、そのまた下の Text.Regex.Posix.Wrap。どういうモジュールかと思って見てみると、
WrapPosix.hsc exports a wrapped version of the ffi imports.
…と言われても、何に対してどうなのか具体的によくわからなかった。 ^^;
=~ の型
それはさておき、 =~ を見ると、
(=~) :: (RegexMaker Regex CompOption ExecOption source, RegexContext Regex source1 target) => source1 -> source -> target
うわっ!(@_@;) この型クラスの制約はどうやって読めばいいのだろうか? QQQ
A Haskell regular expression tutorial によると、とりあえずはシンプルに考えておけと。
this function is polymorphic in both its arguments and its return type; … Here’s a simplified type signature, to give you the idea.
(=~) :: string -> pattern -> result
(I’ve left out the constraints on these type variables. …
なるほど。しかし、引数だけではなく、返り値の型まで多相とは…?
使い方
とりあえず、上記にならって使い方を試してみる。
import Text.Regex import Text.Regex.Posix main = do print $ ("123hogepiyofuga" =~ "(piyo)" :: Bool) # True
最後の :: Bool と型を指定するのがポイント。
最初にマッチした文字列を返すには、
print $ ("123hogepiyofuga" =~ "(piyo)" :: String) # "piyo"
マッチした全ての文字列をリストにして返すには、
print $ ("123hogepiyofuga" =~ "(piyo)" :: [String]) # ["piyo"]
マッチした部分よりも前、マッチした文字列、マッチした文字列の後ろを返したい場合は、
print $ ("123hogepiyofuga" =~ "(piyo)" :: (String,String,String)) # ("123hoge","piyo","fuga")
上記に加えて、先ほどのように部分式にマッチした文字列をリストにしたものも加えたい場合は、
print $ ("123hogepiyofuga" =~ "(piyo)" :: (String,String,String,[String])) # ("123hoge","piyo","fuga",["piyo"])
マッチした文字列の位置とその長さを得たい場合は、Text.Regex.Base をインポートしておいた上で、
print $ ("123hogepiyofuga" =~ "(piyo)" :: (MatchOffset,MatchLength)) # (7,4)
0コメント:
コメントを投稿