読者です 読者をやめる 読者になる 読者になる

Parsec 条件一致した行を無視

Haskell

ちょっとしたログ解析にHaskellのParsecを使ってました。
「行に特定の文字列が含まれていたら無視する」というよくある簡単なフィルタ処理です。C++のBoost.Spirit.Qiであれば

 *(qi::char_ - "[condition]")

のように書く処理。これをParsecでやるには、manyTillを使えばいいようです。

import Text.Parsec
import Text.Parsec.String

parseText :: Parser ()
parseText = do
              manyTill anyChar (try (string "[condition]"))
              return ()

isIgnore :: String -> Bool
isIgnore s = case (parse parseText "" s) of
               Left _  -> False
               Right _ -> True

filterIgnoreLine :: [String] -> [String]
filterIgnoreLine xs = filter (not . isIgnore) xs

main = (putStrLn . unlines . filterIgnoreLine) ["aaa [condition] bbb", "ccc", "ddd [condition]"]
--main = putStrLn . unlines . filterIgnoreLine . lines =<< getContents
ccc

"[condition]"が含まれる行が省かれました。
パースできたかどうかだけわかればいいので、parseText関数のreturnではnulluary tupleを返してます。


それと、述語を逆にするには、「not . pred」のようにすればいいようです。


ファイルを読んでファイルに出力するには、最後の行をコメントインしてコマンドライン上で以下のように指定します。

main < in.log > out.log

テンプレとして使えそうなので、自分用メモとしてこのあたりまで残しておきます。