2017-03-09 9 views
0

巨大なログファイルを解析する必要があります。そして私はハスケルで学習目的のためにそれをやりたいと思っています(私は初心者です)。 ログファイルのレイアウトのようなものです:Haskellでのログファイルの解析

parameter a_parameter_name errors: 5 
error bla bla1 
error bla bla2 
error bla bla bla3 
error bla bla bla4 
error bla bla bla5 
some garbage line 
parameter an_other_parameter_name errors: 7 
error bla bla1 
error bla bla2 
error bla bla3 
error bla bla4 
error bla bla5 
error bla bla6 
error bla bla7 

some garbage line 
some garbage line 
some garbage line 
... 

このログファイルには、2メインラインの種類含まれています:「パラメータ」で始まる

  1. ラインを。
  2. "error"で始まる行。

「エラー」行は、前のパラメータ行に関連しています。 他の行は興味深いものではありません。

私がしたいのは、エラーの数で順序付けられたパラメータとそのエラーを印刷することです。だからここに私が取得したいと思います:

parameter an_other_parameter_name errors: 7 
error bla bla1 
error bla bla2 
error bla bla3 
error bla bla4 
error bla bla5 
error bla bla6 
error bla bla7 
parameter a_parameter_name errors: 5 
error bla bla1 
error bla bla2 
error bla bla bla3 
error bla bla bla4 
error bla bla bla5 

次のコードでは、私はこのリストから興味深い行のリスト

import System.IO 
import Data.List 

interesting :: String -> Bool 
interesting s = isPrefixOf "parameter" s || isPrefixOf "error" s 

main = do 
    logFile <- openFile "log.txt" ReadMode 
    contents <- hGetContents logFile 
    let interestingLines = filter interesting $ lines contents 
    print interestingLines 
    hClose logFile 

を取得し、私はトリプルのリスト構築したいと思います: を[ (パラメータ、errorsNb、[errors])]、私は並べ替えて印刷することができます。 しかし、エラーラインを関連するパラメータラインとどのようにグループ化するかについてはわかりません。しかし、おそらくそれは正しいアプローチではありません... 助けを歓迎します!

オリヴィエ

+1

多くのオプションがあります。 'span'と明示的な再帰を使って' errors'セクションをスライスすることができます。または 'groupBy'があなたのリストを' [[param1]、[err1、err2、err3]、[param2]、[err4]、[param3]] 'として大まかにグループ化し、欲しかった – chi

+0

このためには、[Parsec](https://hackage.haskell.org/package/parsec-3.1.11/docs/Text-Parsec.html)などの解析ライブラリを使用してこのような作業を行います。 breeze – jkeuhlen

+0

これは私のコード・レビューに関する質問と類似していますので、[there](http://codereview.stackexchange.com/questions/147874/kattis-speed-limit-read-irregular-input)をチェックしてください。 – wizzup

答えて

1

私はCIS194の私の解決策(第2週)を修正しました。
バイナリツリーのデータ構造とファイルからの遅延読み込みは、学習に適した練習になります。あなたが提供するサンプルの

type Name = String 
type Count = Int 
data MessageType = Param Name Count 
       | Error String 
       | Unknown String 
        deriving (Show, Eq) 

parseMessage :: String -> MessageType 
parseMessage line = 
    case words line of 
     ("parameter":n:_:c:_) -> Param n (read c) 
     ("error":msg)   -> Error (unwords msg) 
     xs     -> Unknown $ unwords xs 

data LogMessage = LogMessage Name Count [MessageType] 
       deriving (Show, Eq) 

parse :: String -> [MessageType] 
parse = map parseMessage . lines 

isError :: MessageType -> Bool 
isError (Error _) = True 
isError _ = False 


isUnknown :: MessageType -> Bool 
isUnknown (Unknown _) = True 
isUnknown _ = False 

(.||.) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool) 
(.||.) f g a = (f a) || (g a) 

toLogMsg :: [MessageType] -> [LogMessage] 
toLogMsg [] = [] 
toLogMsg (x:xs) = 
    case x of 
     Param n c -> 
      LogMessage n c (takeWhile isError xs) : toLogMsg (dropWhile (isError .||. isUnknown) xs) 
     _   -> toLogMsg $ dropWhile (isError .||. isUnknown) xs 



errMsgList :: [MessageType] -> [String] 
errMsgList = foldr (\(Error m) acc -> m : acc) [] 

toTriple :: [LogMessage] -> [(String, Count, [String])] 
toTriple = foldl(\acc (LogMessage n c xs) -> (n, c, errMsgList xs) : acc) [] 



main :: IO() 
main = do 
     ts <- toLogMsg . parse <$> readFile "./src/2017/so-log.txt" 
     mapM_ print ts 
     mapM_ print (toTriple ts) 

出力は次のようになります。

("an_other_parameter_name",7,["bla bla1","bla bla2","bla bla3","bla bla4","bla bla5","bla bla6","bla bla7"]) 
("a_parameter_name",5,["bla bla1","bla bla2","bla bla bla3","bla bla bla4","bla bla bla5"]) 


LogTriple "a_parameter_name" 5 [Error "bla bla1",Error "bla bla2",Error "bla bla bla3",Error "bla bla bla4",Error "bla bla bla5"] 
LogTriple "an_other_parameter_name" 7 [Error "bla bla1",Error "bla bla2",Error "bla bla3",Error "bla bla4",Error "bla bla5",Error "bla bla6",Error "bla bla7"] 
+0

私はCIS194を知りませんでしたが、これは非常に興味深いようです。コードとリンクをありがとう! – ols

+0

あなたは答えを有用と投票することができますか、その答えに投票してください:) – ArthurVard