2008年7月10日木曜日

Haskell で正規表現 (1)

1. Text.Regex

Haskell で正規表現を使うには、Text.Regex を利用する。

Text.Regex.Posix における正規表現は、POSIX regular expression.

Uses the POSIX regular expression interface in Text.Regex.Posix

POSIX regular expression については、

POSIX とは Wikipedia によると、

POSIXポジックスPortable Operating System Interface)とは、異なる実装のUNIX OSを始めとする各種OSに共通のAPIを定め、移植性の高いアプリケーションソフトウェアの開発を容易にすることを目的としてIEEEが策定したアプリケーションインタフェイス規格。POSIXの「X」はUNIX互換OSにXがつく名前が多いことからつけられたもの。

ふつうのHaskellプログラミング には、正規表現を使う方法が説明されていない。その代わりに、特定の文字列が含まれるか検査する関数に対して、次のように解説している。、

この関数では行lineに文字列patternが含まれているかを判定したいのですが、意外にも、そのものズバリの関数はHaskellのPreludeモジュールにはありません。(p93)

Haskell では、文字列に対するマッチングを、リスト処理の観点から行うのが普通なのだろうか (?_?)

 

2. matchRegex

mkRegex によって Regex 型の値を生成し、それが対象の文字列にマッチするか matchRegex で調べる。
import Text.Regex
main = do print $ matchRegex (mkRegex "hoge") "hogepiyofuga"
          print $ matchRegex (mkRegex "piga") "hogepiyofuga"
結果は、Just [] と Nothing 。 Nothing の方はいいのだけれど Just [] というのは何だろう (?_?)

Returns: Just strs if the match succeeded (and strs is the list of subexpression matches),

と書かれているがよくわからなかった。 ^^; list of subexpression が空なのはなぜ? → 以下の 追記(2008.10.24) を参照。

ちなみに、 mkRegex のところの正規表現を ( ) で囲むと、Just [“hoge”] というように返されるようだ。

 

subexpression

追記(2008.10.24) : subexpression というのは「部分式」と訳される。

Rx - Posix Basic Regular Expressions によると、

部分式とは、\(\)とに囲まれた正規表現である。

Regular expression - Wikipedia, the free encyclopedia にも同様に書かれている。

\( \)
Defines a marked subexpression. The string matched within the parentheses can be recalled later (see the next entry, \n). A marked subexpression is also called a block or capturing group.

つまり、上記で引用した通り、matchRegex 関数において Just で包んで返されるものは subexpression にマッチしたものということ。

 

3. matchRegexAll

matchRegexAll を使うと、

「マッチする前、マッチしたもの、マッチした後、 subexpression matches 」

を取得できる。やはりこの subexpression が謎。 (+_+)  → 上記の 追記(2008.10.24) を参照。
case 式を使って場合分けをするコードを書いてみると、

import Text.Regex
main = do putStrLn $ case matchRegexAll (mkRegex "piyo") "123hogepiyofuga" of
                       Just x -> show x
                       otherwise -> "Nothing"

結果は ("123hoge","piyo","fuga",[]) のようにタプルで返される。 例えば、マッチした後の結果だけが必要であれば、 case 式の中で Just (_, _, x, _) –> x のようにマッチを行う。Just の中身についてはドキュメントを見ると、

  Just ( everything before match,
         portion matched,
         everything after the match,
         subexpression matches )

 

後で読む

うーん、難しくてわからない。 (@_@;) がんばって勉強しよ~。

 

関連記事