代码之家  ›  专栏  ›  技术社区  ›  dragonmantank

如何从Linux上的日志文件中提取XML块

  •  1
  • dragonmantank  · 技术社区  · 16 年前

    我有一个日志文件,如下所示:

    2010-05-12 12:23:45 Some sort of log entry
    2010-05-12 01:45:12 Request XML: <RootTag>
    <Element>Value</Element>
    <Element>Another Value</Element>
    </RootTag>
    2010-05-12 01:45:32 Response XML: <ResponseRoot>
    <Element>Value</Element>
    </ResponseRoot>
    2010-05-12 01:45:49 Another log entry
    

    我要做的是提取请求和响应XML(并最终将它们转储到自己的单个文件中)。我有一个使用egrep的类似解析器,但是XML都在一行上,而不是像上面那样的多行上。

    日志文件也有点大,达到了500-600兆每日志。我将通过一个PHP脚本读取较小的日志,并使用regex匹配,但是这样一个大文件所需的内存量很可能会杀死该脚本。

    有没有一种简单的方法可以使用Linux设备上的内置工具(在本例中是CentOS)来提取多行代码,或者我需要咬紧牙关,使用Perl或PHP来读取整个文件来提取代码?

    3 回复  |  直到 16 年前
        1
  •  2
  •   FMc TLP    16 年前
    # Example usage:
    # perl script.pl data.xml RootTag > RootTag.xml
    
    use strict;
    use warnings;
    
    my $tag = pop;
    
    while (<>){
        if ( s/.*(<$tag>)/$1/ .. s/(<(\/)$tag>).*/$1/ ){
            print;
            last if $2;
        }
    }
    

    有关详细信息,请参阅文档 flip-flop operator .

        2
  •  2
  •   David Z    16 年前

    听起来像是工作 sed (我很想说“超级”—)

    sed -n '/^<.\+>/H; /\(Request\|Response\) XML/{s/^.*</</;x;p}; ${x;p}' xmllog
    

    在哪里? xmllog 是日志文件的名称。一开始你会得到一个空行,但可以用过滤掉 egrep '.+' 甚至只是 tail -n +2 .

    通过解释, 塞德 是由匹配条件和相应操作列表组成的程序的一个小解释程序。 塞德 逐行运行文件(因此名称为“流编辑器”->“sed”),对于每一行,对于程序中与该行上的文本匹配的每个条件,它应用相应的操作。在这种情况下:

    /^<.\+>/
    

    是一个正则表达式条件,它与包含 < 后跟任何字符( . )重复一次或多次( \+ ) > -基本上,任何带有XML标记的行。关联的操作是 H 它将行附加到“保持缓冲区”。另一个条件是

    /\(Request\|Response\) XML/
    

    当然,它是一个与 Request Response 后面跟着一个空格,然后 XML . 相应的动作是

    {s/^.*</</;x;p}
    

    哪个先做一个替换( s )行首( ^ )后跟任何字符( . )重复任何次数( * ) < ,只是 < . 基本上,在行中的第一个XML标记之前就可以去掉任何东西。然后它切换( x )用“hold buffer”(包含前一条日志消息的XML)读取的行并打印( p )刚从保留缓冲区换入的内容。最后,

    $
    

    匹配输入的结尾,以及 {x;p} 再次,只需将保留缓冲区的内容交换到“打印缓冲区”中,然后打印它。

    您可以更改命令以满足您的需要,例如,如果您需要一些东西来分隔不同的记录,这将在它们之间放置一个空白行:

    sed -n '/^<.\+>/H; /\(Request\|Response\) XML/{s/^.*</\n</;x;p}; ${x;p}' xmllog
    

    (在这种情况下,当然,不要使用 egrep 在开始时过滤空白行。

        3
  •  1
  •   Brian Roach    16 年前

    你的问题意味着你的想法不正确;如果有一种方法可以用一种语言来做你想做的事情(有…)。然后你可以用任何语言来做。

    没有理由将整个日志读取到内存中。你只需一行一行地阅读它,然后提取你想要的信息。你只需要保持一个状态,你在哪里(不在标签,内根标签,内响应,等等)和处理数据,你希望。