Parsec 条件一致した行を無視
ちょっとしたログ解析に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
テンプレとして使えそうなので、自分用メモとしてこのあたりまで残しておきます。