【问题标题】:Parsing FIX protocol message from log file in regex?从正则表达式的日志文件中解析 FIX 协议消息?
【发布时间】:2014-04-04 10:54:15
【问题描述】:

我需要从一个大型日志文件中提取所有 FIX 消息,该文件可能包含 10000 到 20000 条 FIX 协议消息。我期望获取的 FIX 协议消息将以 8=FIX 开头并以 |10= 一些 CheckSum 值结尾,该值可以是任何值,然后是分隔符 '|'

例如8=FIXT.1.1|9=449|35=AE|34=1734|49=REPOFIXUAT|52=20140402-11:38:34|56=TR_UAT_VENDOR|1128=8|15=GBP|31=1.7666|32=50000000.00|55=GBP/USD|60=20140402-11:07:33|63=B|64=20140415|65=OR|75=20140402|150=F|167=FOR|194=1.7654|195=0.0012|460=4|571=7852455|1003=2 USD|1056=88330000.00|1057=N|552=1|54=2|37=20140402-12:36:48|11=NOREF|453=4|448=ZERO|447=D|452=3|448=MBY2|447=D|452=1|448=LMEB|447=D|452=16|448=DOR|447=D|452=11|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|10=111|

目前,我正在将此模式用于正则表达式

Pattern pattern = Pattern.compile("8=FIX(.*?)10=(.*?)|");

但在上述模式中,我只能提取消息直到10=,但不能提取校验和值,并且可能存在某些 FIX 消息自定义标签类似于 8410=TEST| 的情况如下:

8=FIXT.1.1|9=73|35=0|34=560|49=RTNSFIXUAT|8410=TEST|52=20140403-01:50:21|56=TR_UAT_VELOCITY|1128=8|10=206|

在上面,我会得到价值

“8=FIXT.1.1|9=73|35=0|34=560|49=RTNSFIXUAT|84”(X - 我想要完整的消息直到标签 10 校验和值 206

请找到日志文件sn-p如下:

>02-04-14 11:38:33.559|QFJ Message Processor|input/REPOFIXInput1|INFO|quickfix.outgoing: 8=FIXT.1.1|9=71|35=0|34=1731|49=TR_UAT_VENDOR|52=20140402-11:38:33.557|56=REPOFIXUAT|10=147|
02-04-14 11:38:34.713|SocketConnectorIoProcessor-1.0|input/REPOFIXInput1|INFO|quickfix.incoming: 8=FIXT.1.1|9=449|35=AE|34=1734|1128=8|49=REPOFIXUAT|56=TR_UAT_VENDOR|52=20140402-11:38:34|552=1|54=2|37=20140402-12:36:48|11=NOREF|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|453=4|448=ZERO|452=3|447=D|448=MBY2|452=1|447=D|448=LMEB|452=16|447=D|448=DOR|452=11|447=D|571=7852455|1003=2 USD|150=F|32=50000000.00|15=GBP|1056=88330000.00|31=1.6666|194=1.6654|195=0.0012|64=20140415|63=B|60=20140402-11:07:33|75=20140402|1057=N|460=4|167=FOR|65=OR|55=GBP/USD|10=111|
02-04-14 11:38:35.004|QFJ Message Processor|input/REPOFIXInput1|INFO|Received FIX application message: 8=FIXT.1.1|9=449|35=AE|34=1734|49=REPOFIXUAT|52=20140402-11:38:34|56=TR_UAT_VENDOR|1128=8|15=GBP|31=1.7666|32=50000000.00|55=GBP/USD|60=20140402-11:07:33|63=B|64=20140415|65=OR|75=20140402|150=F|167=FOR|194=1.7654|195=0.0012|460=4|571=7852455|1003=2 USD|1056=88330000.00|1057=N|552=1|54=2|37=20140402-12:36:48|11=NOREF|453=4|448=ZERO|447=D|452=3|448=MBY2|447=D|452=1|448=LMEB|447=D|452=16|448=DOR|447=D|452=11|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|10=111|

【问题讨论】:

  • 使用 NIX 系统中可用的 cut 命令或在 windows 上的 cygwin 中使用它。也许是 2 分钟的工作。

标签: java regex pattern-matching fix-protocol


【解决方案1】:

如果我理解正确,你想保留:

  • 8=FIX 之后但|10=... 之前的所有内容
  • 也是|10=value| 中的值

这是一个例子:

String input = ">02-04-14 11:38:33.559|QFJ Message Processor|input/REPOFIXInput1|INFO|quickfix.outgoing: 8=FIXT.1.1|9=71|35=0|34=1731|49=TR_UAT_VENDOR|52=20140402-11:38:33.557|56=REPOFIXUAT|10=147|\r\n"
                       + "02-04-14 11:38:34.713|SocketConnectorIoProcessor-1.0|input/REPOFIXInput1|INFO|quickfix.incoming: 8=FIXT.1.1|9=449|35=AE|34=1734|1128=8|49=REPOFIXUAT|56=TR_UAT_VENDOR|52=20140402-11:38:34|552=1|54=2|37=20140402-12:36:48|11=NOREF|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|453=4|448=ZERO|452=3|447=D|448=MBY2|452=1|447=D|448=LMEB|452=16|447=D|448=DOR|452=11|447=D|571=7852455|1003=2 USD|150=F|32=50000000.00|15=GBP|1056=88330000.00|31=1.6666|194=1.6654|195=0.0012|64=20140415|63=B|60=20140402-11:07:33|75=20140402|1057=N|460=4|167=FOR|65=OR|55=GBP/USD|10=111|\r\n"
                       + "02-04-14 11:38:35.004|QFJ Message Processor|input/REPOFIXInput1|INFO|Received FIX application message: 8=FIXT.1.1|9=449|35=AE|34=1734|49=REPOFIXUAT|52=20140402-11:38:34|56=TR_UAT_VENDOR|1128=8|15=GBP|31=1.7666|32=50000000.00|55=GBP/USD|60=20140402-11:07:33|63=B|64=20140415|65=OR|75=20140402|150=F|167=FOR|194=1.7654|195=0.0012|460=4|571=7852455|1003=2 USD|1056=88330000.00|1057=N|552=1|54=2|37=20140402-12:36:48|11=NOREF|453=4|448=ZERO|447=D|452=3|448=MBY2|447=D|452=1|448=LMEB|447=D|452=16|448=DOR|447=D|452=11|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|10=111|";
    Pattern p = Pattern.compile("8=FIX(.+)(?<=\\|)10=(.+?)(?=\\|)", Pattern.MULTILINE);
    Matcher m = p.matcher(input);
    while (m.find()) {
        System.out.println(m.group());
        System.out.println("\t" + m.group(1));
        System.out.println("\t" + m.group(2));
    }

输出

8=FIXT.1.1|9=71|35=0|34=1731|49=TR_UAT_VENDOR|52=20140402-11:38:33.557|56=REPOFIXUAT|10=147
    T.1.1|9=71|35=0|34=1731|49=TR_UAT_VENDOR|52=20140402-11:38:33.557|56=REPOFIXUAT|
    147
8=FIXT.1.1|9=449|35=AE|34=1734|1128=8|49=REPOFIXUAT|56=TR_UAT_VENDOR|52=20140402-11:38:34|552=1|54=2|37=20140402-12:36:48|11=NOREF|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|453=4|448=ZERO|452=3|447=D|448=MBY2|452=1|447=D|448=LMEB|452=16|447=D|448=DOR|452=11|447=D|571=7852455|1003=2 USD|150=F|32=50000000.00|15=GBP|1056=88330000.00|31=1.6666|194=1.6654|195=0.0012|64=20140415|63=B|60=20140402-11:07:33|75=20140402|1057=N|460=4|167=FOR|65=OR|55=GBP/USD|10=111
    T.1.1|9=449|35=AE|34=1734|1128=8|49=REPOFIXUAT|56=TR_UAT_VENDOR|52=20140402-11:38:34|552=1|54=2|37=20140402-12:36:48|11=NOREF|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|453=4|448=ZERO|452=3|447=D|448=MBY2|452=1|447=D|448=LMEB|452=16|447=D|448=DOR|452=11|447=D|571=7852455|1003=2 USD|150=F|32=50000000.00|15=GBP|1056=88330000.00|31=1.6666|194=1.6654|195=0.0012|64=20140415|63=B|60=20140402-11:07:33|75=20140402|1057=N|460=4|167=FOR|65=OR|55=GBP/USD|
    111
8=FIXT.1.1|9=449|35=AE|34=1734|49=REPOFIXUAT|52=20140402-11:38:34|56=TR_UAT_VENDOR|1128=8|15=GBP|31=1.7666|32=50000000.00|55=GBP/USD|60=20140402-11:07:33|63=B|64=20140415|65=OR|75=20140402|150=F|167=FOR|194=1.7654|195=0.0012|460=4|571=7852455|1003=2 USD|1056=88330000.00|1057=N|552=1|54=2|37=20140402-12:36:48|11=NOREF|453=4|448=ZERO|447=D|452=3|448=MBY2|447=D|452=1|448=LMEB|447=D|452=16|448=DOR|447=D|452=11|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|10=111
    T.1.1|9=449|35=AE|34=1734|49=REPOFIXUAT|52=20140402-11:38:34|56=TR_UAT_VENDOR|1128=8|15=GBP|31=1.7666|32=50000000.00|55=GBP/USD|60=20140402-11:07:33|63=B|64=20140415|65=OR|75=20140402|150=F|167=FOR|194=1.7654|195=0.0012|460=4|571=7852455|1003=2 USD|1056=88330000.00|1057=N|552=1|54=2|37=20140402-12:36:48|11=NOREF|453=4|448=ZERO|447=D|452=3|448=MBY2|447=D|452=1|448=LMEB|447=D|452=16|448=DOR|447=D|452=11|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|
    111

备注

  • 此示例未针对性能进行优化。
  • 您可能希望删除此Pattern 的“多行”标志,并使用常量Pattern 分别处理每一行
  • 如果你这样做,你将不得不为每一行重新初始化一个Matcher,但你可以在if语句而不是while语句中调用find,假设你每行有一个日志
  • 存储匹配值由您决定

【讨论】:

  • 谢谢 Mena,上面的示例方法对我有用,但如果我通过我的日志文件进行处理,它不会给出结果。我相信这是由于 \r\n 您已明确添加到上述代码以用于模式匹配。而且,正如我在问题中所写的那样,我需要处理来自文件的 10 到 20K FIX 消息。所以在这种情况下,我需要写 `m.group(), m.group(1), m.group(2)` 直到 20K。以上请指教。问候
  • @Ankit 如注释中所述,您想要的 Pattern 可能没有多行标志(只需将其删除),因为您将逐行处理文件。还提到:存储匹配的值取决于您,无论是将它们放在文件、数据库中,还是(由于大小而风险更大)将它们存储在内存中。如您所见,您实际上只需要第 1 组和第 2 组;主组是整场比赛。
  • 再次非常感谢,但到目前为止我并不担心保存这些消息。通过使用上面的正则表达式,我仍然没有从日志中获得预期的消息(可能是我遗漏了一些东西)但是我在网上花了一些时间在 Regex 教程上之后尝试了8=FIX(.*?)(?&lt;=)~10=(.*?)~ regex 表达式,这对我有用。请建议它适用于所有场景,或者我根据上述要求缺少任何特定场景,因为我是正则表达式世界的新手。
【解决方案2】:

因此,将所有 FIX 消息保存到数据库是一个好主意,一旦它们被“处理”并避免所有这些。

【讨论】:

  • 数据库会比写入文件慢得多。
  • 是的,所以使用消息代理完成工作,然后在此处保留所需的报告。
【解决方案3】:

我了解我在 FIX 消息中使用 "|" (pipe) 作为分隔符的问题,但它也出现在日志 cmets (02-04-14 14:30:45.139|QFJ Timer|input/FIXInput1|INFO|Sending FIX session message: 8=FIXT.1.1|9=71|35=0|34=2072|49=UAT|52=20140402-14:30:45.139|56=FIXUAT|10=140| 02-04-14 14:30:45.141|QFJ Timer|input/FIXInput1|DEBUG|FIX message as XML: <?xml version="1.0" encoding="ISO-8859-1"?><message>) 中,直到 10=checksum 结束时才处理模式,现在在制作之后在我的上述模式中,FIX 消息标记与 "~" (tilde) 之间的分隔符即'8=FIX(.?)(??)~' 然后它对我有用这类似于您作为上述解决方案提供的 REGEX。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多