2017-03-09 1 views
0

거대한 로그 파일을 구문 분석해야합니다. 그리고 나는 하스켈에서 학습 목적을 위해 그것을하고 싶습니다 (저는 초보자입니다).하스켈에서 로그 파일 구문 분석

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. 줄은 "오류"로 시작합니다.

"오류"줄은 이전 매개 변수 줄과 관련이 있습니다. 다른 줄은 흥미롭지 않습니다.

내가 뭘하고 싶은지는 오류의 수에 따라 매개 변수와 오류를 인쇄하는 것입니다. 그래서 여기 내가 좀하고 싶습니다 : 다음 코드와

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

이 코드 검토 내 질문에 일부 유사점을, 당신은 [거기] (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