2016-02-12 2 views
-1

Я играл с журналами разбора (PostgreSQL), которые могут содержать многострочные записи.Multi-line * non * match with attoparsec

2016-01-01 01:01:01 entry1 
2016-01-01 01:01:02 entry2a 
    entry2b 
2016-01-01 01:01:03 entry3 

Так что - с помощью сценария Perl или Python, я бы просто захватить следующую строку, и если он не начинал с меткой времени добавить его к предыдущей записи в журнале. Какой разумный способ приблизиться к этому с помощью attoparsec подключен до io-streams? Я явно хочу что-то сделать с lookAhead и неспособным сопоставить временную метку, но мой мозг просто что-то упустил.


Нет, до сих пор не видно. Я снял все, что у меня есть. Разбор одной строки прост. Я не могу понять, как анализировать «до» другого шаблона синтаксического анализа - я могу видеть функцию lookAhead, которую я могу использовать, но я не вижу, как это вписывается в условие «нет».

Я не вижу, как я могу соответствовать. Весьце возможным мой мозг охватил.

{-# LANGUAGE OverloadedStrings #-} 

module DummyParser (
    LogStatement (..), parseLogLine 
    -- and, so we can test it... 
    , LogTimestamp , parseTimestamp 
    , parseSqlStmt 
    , newLineAndTimestamp 
) where 

{- we want to parse... 
TIME001 statement: SELECT true; 
TIME002 statement: SELECT 'b', 
    'c'; 
TIME003 statement: SELECT 3; 
-} 

import   Data.Attoparsec.ByteString.Char8 
import qualified Data.ByteString.Char8   as B 

type LogTimestamp = Int 

data LogStatement = LogStatement { 
    l_ts :: LogTimestamp 
    ,l_sql :: String 
} deriving (Eq, Show) 


restOfLine :: Parser B.ByteString 
restOfLine = do 
    rest <- takeTill (== '\n') 
    isEOF <- atEnd 
    if isEOF then 
     return rest 
    else 
     (char '\n') >> return rest 


-- e.g. TIME001 
parseTimestamp :: Parser LogTimestamp 
parseTimestamp = do 
    string "TIME" 
    digits <- count 3 digit 
    return (read digits) 


-- e.g. statement: SELECT 1 
parseSqlStmt :: Parser String 
parseSqlStmt = do 
    string "statement: " 
    -- How can I match until the next timestamp? 
    sql <- restOfLine 
    return (B.unpack sql) 


newLineAndTimestamp :: Parser LogTimestamp 
newLineAndTimestamp = (char '\n') *> parseTimestamp 


spaces :: Parser() 
spaces = do 
    skipWhile (== ' ') 


-- e.g. TIME001 statement: SELECT * FROM schema.table; 
parseLogLine :: Parser LogStatement 
parseLogLine = do 
    log_ts <- parseTimestamp 
    spaces 
    log_sql <- parseSqlStmt 
    let ls = LogStatement log_ts log_sql 
    return ls 

EDIT: Так, это было то, что я, наконец, закончил с благодарностью, чтобы arrowd Поможем

isTimestampNext = lookAhead parseTimestamp *> pure() 

parseLogLine :: Parser LogStatement 
parseLogLine = do 
    log_ts <- parseTimestamp 
    spaces 
    log_sql <- parseSqlStmt 
    extraLines <- manyTill restOfLine (endOfInput <|> isTimestampNext) 
    let ls = LogStatement log_ts (log_sql ++ (B.unpack $ B.concat extraLines)) 
    return ls 
+0

Я не думаю, что вам нужно посмотреть на это. Просто проанализируйте время разбора, сопоставляя метки времени, и только _within_ каждый элемент времени анализирует подзаголовки. – leftaroundabout

+0

Хм - Кажется, я понимаю, что вы имеете в виду. Я думал об этом линейным образом. Если я сделаю свой разделитель «\ n », мы можем полностью обойти эту проблему. Спасибо. Я попробую сегодня вечером, если у меня появится шанс. –

+0

Не кажется слишком сложным с 'attoparsec', но вы должны опубликовать свою попытку до сих пор. – Jubobs

ответ

1

комбинатора я совместно на многих attoparsec вопросы:

notFollowedBy p = p >> fail "not followed by" 

Ваш решение было бы чем-то вроде

parseLogLine :: Parser LogStatement 
parseLogLine = do 
    log_ts <- parseTimestamp 
    spaces 
    log_sql <- parseSqlStmt 
    newlineLeftover <- ((notFollowedBy parseTimestamp) *> parseSqlStmt) <|> pure "" 
    let ls = LogStatement log_ts (log_sql ++ newlineLeftover 
    return ls 

Правая сторона *> для выражения newlineLeftOver потребует дополнительной работы, я думаю, но общая идея такова.

+0

Спасибо. Близкие идеи думать о неудаче и '*>' обеспечить желаемое возвращаемое значение заставили его щелкнуть для меня. –

 Смежные вопросы

  • Нет связанных вопросов^_^