【问题标题】:Read log file in R so that each row starts with timestamp在 R 中读取日志文件,以便每一行都以时间戳开头
【发布时间】:2020-11-26 16:35:34
【问题描述】:

我有一个包含此类数据的日志文件:

2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ResourceLoaderHelper: 10 - Trying to upload data
2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ResourceLoaderHelper: 66 - Trying to upload data
2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ValidationXmlParser: 127 - No META-Only annotation
2020-07-28 14:48:00 (pool-2-thread-1id) DEBUG MessageWriter: 55 - Send message ErrorOutputMessage(super=NotificationOutputMessage(super=OutputMessage(type=null, messageId=116345, reqId=af24112))), error=ErrorOutputMessage.Error(code=400, text={
  "errors": [
    "Message type error"
  ]
})) to exchange FOS 
2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ValidatorFactoryImpl: 578 - Scoped message interpolator.

我尝试以这种方式读取该文件:

data <- readr::read_lines(file = "log_data.log", progress = FALSE)
log_df <- setDT(tibble::enframe(data, name = NULL))

但是这个数据框看起来像这样:

              value
1   2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ResourceLoaderHelper: 10 - Trying to upload data
 
2   2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ResourceLoaderHelper: 66 - Trying to upload data
3   2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ValidationXmlParser: 127 - No META-Only annotation
4   2020-07-28 14:48:00 (pool-2-thread-1id) DEBUG MessageWriter: 55 - Send message ErrorOutputMessage(super=NotificationOutputMessage(super=OutputMessage(type=null, messageId=116345, reqId=af24112))), error=ErrorOutputMessage.Error(code=400, text={
5     "errors": [
6         "Message type error"
7     ]
8   })) to exchange FOS 
9   2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ValidatorFactoryImpl: 578 - Scoped message interpolator.

所以你看到第 4 行被分成几行,以为是它。我怎么能读取这个日志文件,所以它知道每一行都必须以时间戳开头?我应该以某种方式使用正则表达式吗?

【问题讨论】:

    标签: r regex dataframe


    【解决方案1】:

    您可以使用正则表达式删除所有不跟日期的换行符:

    log_string <- '2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ResourceLoaderHelper: 10 - Trying to upload data
    2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ResourceLoaderHelper: 66 - Trying to upload data
    2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ValidationXmlParser: 127 - No META-Only annotation
    2020-07-28 14:48:00 (pool-2-thread-1id) DEBUG MessageWriter: 55 - Send message ErrorOutputMessage(super=NotificationOutputMessage(super=OutputMessage(type=null, messageId=116345, reqId=af24112))), error=ErrorOutputMessage.Error(code=400, text={
      "errors": [
        "Message type error"
      ]
    })) to exchange FOS 
    2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ValidatorFactoryImpl: 578 - Scoped message interpolator.'
    
    readr::read_lines(
        stringr::str_replace_all(
            log_string,
        
            # Regular expression
            '(\\r?\\n|\\r)(?!\\d{4}-(\\d{2}[-: ]){5})', '')
    )
    
    
    [1] "2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ResourceLoaderHelper: 10 - Trying to upload data"                                                                                                                                                                                                                      
    [2] "2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ResourceLoaderHelper: 66 - Trying to upload data"                                                                                                                                                                                                                      
    [3] "2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ValidationXmlParser: 127 - No META-Only annotation"                                                                                                                                                                                                                    
    [4] "2020-07-28 14:48:00 (pool-2-thread-1id) DEBUG MessageWriter: 55 - Send message ErrorOutputMessage(super=NotificationOutputMessage(super=OutputMessage(type=null, messageId=116345, reqId=af24112))), error=ErrorOutputMessage.Error(code=400, text={  \"errors\": [    \"Message type error\"  ]})) to exchange FOS "
    [5] "2020-07-28 10:07:01 (pool-3-thread-5id) DEBUG ValidatorFactoryImpl: 578 - Scoped message interpolator."
    
    

    (\\r?\\n|\\r) 匹配不同版本的换行符。

    (?!\\d{4}-(\\d{2}[-: ]){5}) 是与日期时间匹配的否定前瞻(复制自 EvilSmurf 的答案)。

    【讨论】:

    • 我不知道 R,所以我认为你已经完成了它(我也没有正确阅读,french_fries 想要排除任何不以时间戳开头的额外行) - 仍然不了解为什么有人反对我们的答案
    • 我已将你“设置回”为 0 ;)
    • 同上。可能有一种更优雅的方法来解决这个问题,正如我所看到的,您要么删除额外的换行符(如此处所示),要么忽略换行符并通过日期时间的存在拆分字符串(有风险如果在消息中使用日期时间)。
    【解决方案2】:

    可以采用两遍方法:

    1. 在 Notepad++ 中,使用正则表达式替换 \R++(?!\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} ) 模式和一些占位符替换,例如 &lt;L1nBre@k&gt;Start the regex engine 看看这个表达式是如何工作的。
    2. 读入文件后,恢复换行符:
    data <- gsub('<L1nBre@k>', '\n', data, fixed=TRUE)
    

    \R++(?!\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} )解释

    --------------------------------------------------------------------------------
      \R++                     line break sequence (1 or more times, as many
                               as possible), matched possessively
    --------------------------------------------------------------------------------
      (?!                      look ahead to see if there is not:
    --------------------------------------------------------------------------------
        \d{4}                    digits (0-9) (4 times)
    --------------------------------------------------------------------------------
        -                        '-'
    --------------------------------------------------------------------------------
        \d{2}                    digits (0-9) (2 times)
    --------------------------------------------------------------------------------
        -                        '-'
    --------------------------------------------------------------------------------
        \d{2}                    digits (0-9) (2 times)
    --------------------------------------------------------------------------------
                                 ' '
    --------------------------------------------------------------------------------
        \d{2}                    digits (0-9) (2 times)
    --------------------------------------------------------------------------------
        :                        ':'
    --------------------------------------------------------------------------------
        \d{2}                    digits (0-9) (2 times)
    --------------------------------------------------------------------------------
        :                        ':'
    --------------------------------------------------------------------------------
        \d{2}                    digits (0-9) (2 times)
    --------------------------------------------------------------------------------
                                 ' '
    --------------------------------------------------------------------------------
      )                        end of look-ahead
    

    【讨论】:

    • R 的正则表达式实现需要额外的反斜杠,因为它(“\”)在 R 和正则表达式中都是转义字符。您的答案可能在其他情况下有用,但在这里不行。
    • @IRTFM 你误解了我的意图:正则表达式字符串在 Notepad++ 中使用是正确的。该文件需要在 R 中使用前进行预处理。
    • 我在回答它对使用 R 的人有多么有用。所以我认为是你误解了这个问题。如果您承认这解决了另一个问题,那么我认为您应该删除它。
    【解决方案3】:

    是的,我认为正则表达式是一个不错的方法

    您使用哪种编程语言?

    在 python 格式中,表达式是这样的:

    \d{4}-(\d{2}[-: ]){5}(?P<your_data>[\s\S]*?)(?=\s*(\d{4}-(\d{2}[-: ]){5}|$))
    

    我给你做了个例子here

    更新:

    如果您实际上只想将行与时间戳匹配,您可以将正则表达式模式简化为:

    \d{4}-(?:\d{2}[-: ]){5}[^\n]*
    

    【讨论】:

    • 感谢它的 R 工作室。我应该把那个正则表达式放在哪里?
    • for reg ex in R 看看:databraineo.com/ki-training-resources/r-programmierung/… 但从我读到的内容支持量词和分组。也许不是“?P”中的“命名组”,而只是使用捕获组并将其编入索引
    • @EvilSmurf:R 的正则表达式实现需要额外的反斜杠,因为它在 R 和正则表达式中都是转义字符。您的答案可能在其他情况下有用,但在这里不行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多