2017-10-11 62 views
1

我需要从类似于下面的sql日志中解析和提取值。多行java的正则表达式

SQL^^0001^^ABCDEF^^26^^XYZ 
SQL^^0002^^ABCDEF^^26^^XYZ 
abc 
<>()_asc wHERE 
SQL^^0003^^ABCDEF^^12^^XYZ 
SQL^^0004^^ABCDEF^^28^^XYZ 

但是日志总是不是单行。我有一个可以捕获的正则表达式如果它是单行的。除了最后一个元素外,这些字段的长度也是固定的。最后一个元素的长度可能不同。

(\w{3})\W{2}(\d{4})\W{2}(\w{6})\W{2}(\d{2})\W{2}(.*) 

^^ is the delimiter but can be any other value also. 

没有固定的行尾字符,但我需要捕获,直到下一行SQL在这种情况下。 如何解析日志并提取它们,如果它的多行日志。我在Java中尝试。 Java或Scala是首选。

+0

正则表达式的其余部分不是输入解析跨多行的好工具。如果所有感兴趣的数据记录都以相同的模式开始,那么您可以做的一件事是将日志读入单行文本(不换行'\ n'字符),然后在开始时将'split()记录模式。之后,您将解析各个元素。 – jwvh

+0

在每行的开头是否有以“SQL ^^'开头的新记录?要正确处理这种情况,我们需要知道确切的记录起始模式。尝试[** this regex **](https://regex101.com/r/OrIqvz/1)。 –

+0

很高兴为你效劳。如果我的回答对你有帮助,也请考虑积极投票。 –

回答

0

您可以利用这样的事实,即每个记录始终以3个字符后跟^^开头。因此,您匹配的最后一个字段应匹配任何不以该模式开头的行。如果^^只是一个示例,则可以使用整个\w{3}\W{2}\d{4}\W{2}\w{6}\W{2}\d{2}\W{2}模式作为分隔符而不是^^

使用

(?m)^(\w{3})\W{2}(\d{4})\W{2}(\w{6})\W{2}(\d{2})\W{2}(.*(?:\r?\n(?!\w{3}\^\^).*)*) 

regex demo。如果^^只是一个占位符,如上所述,请将​​替换为(?!\w{3}\W{2}\d{4}\W{2}\w{6}\W{2}\d{2}\W{2})。或者,也许更短的一个也会这样做:(?!\w{3}\W{2}\d{4}\b)

详细

  • (?m)^ - 一行的开始((?m)Pattern.MULTILINE嵌入标志的选项,使得^匹配的线开始,而不是字符串开始位置)
  • (\w{3}) - 组1:3字词
  • \W{2} - 2个非单词字符
  • (\d{4}) - 第2组:四位数字
  • \W{2} - 2非字字符
  • (\w{6}) - 组3:6个字字符
  • \W{2} - 2非字字符
  • (\d{2}) - 组4:2位数字
  • \W{2} - 2个非字字符
  • (.*(?:\r?\n(?!\w{3}\^\^).*)*) - 第5组:
    • .* - 连续零个或多个 - 任何0+比换行符字符等,尽可能多的
    • (?:\r?\n(?!\w{3}\^\^).*)*字符:
      • \r?\n(?!\w{3}\W{2}) - CRLF或LF换行符后面没有与3字,然后2个非字字符
      • .* - 行