Php 如何在Linux上从日志文件中提取XML块
我有一个如下所示的日志文件:Php 如何在Linux上从日志文件中提取XML块,php,regex,linux,perl,command-line,Php,Regex,Linux,Perl,Command Line,我有一个如下所示的日志文件: 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: <Respon
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
2010-05-12 12:23:45某种日志条目
2010-05-12 01:45:12请求XML:
价值
另一个价值
2010-05-12 01:45:32响应XML:
价值
2010-05-12 01:45:49另一个日志条目
我想做的是提取请求和响应XML(并最终将它们转储到它们自己的单个文件中)。我有一个使用egrep的类似解析器,但是XML都在一行上,而不是像上面那样的多行
日志文件也有点大,达到500-600兆/日志。我会通过PHP脚本读取较小的日志,并使用正则表达式匹配,但如此大的文件所需的内存量很可能会杀死脚本
有没有一种简单的方法可以使用Linux机器上的内置工具(本例中是CentOS)提取多行代码,还是我必须咬紧牙关,使用Perl或PHP读取整个文件来提取它?你的问题表明你的想法不对;如果有一种方法可以用一种语言实现你的要求(有)。。。然后你可以用任何语言来做
没有理由将整个日志读取到内存中。你只要逐行阅读并提取你想要的信息。你只需要保持一个状态,知道你在哪里(不在标签、根标签内、响应区内等等),然后按照你的意愿处理数据。你的问题意味着你没有正确思考;如果有一种方法可以用一种语言实现你的要求(有)。。。然后你可以用任何语言来做
# 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;
}
}
没有理由将整个日志读取到内存中。你只要逐行阅读并提取你想要的信息。您只需保持您所在位置的状态(不在标记中、在RootTag内部、在ResponseRoot内部等),并根据需要处理数据。#示例用法:
# 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;
}
}
#perl script.pl data.xml RootTag>RootTag.xml
严格使用;
使用警告;
我的$tag=pop;
而(){
如果(s/*()/$1/.s/().*/$1/){
打印
最后,如果2美元;
}
}
有关使用示例的详细信息,请参阅文档
#perl script.pl data.xml RootTag>RootTag.xml
严格使用;
使用警告;
我的$tag=pop;
而(){
如果(s/*()/$1/.s/().*/$1/){
打印
最后,如果2美元;
}
}
有关的详细信息,请参阅文档。听起来像是
sed
的工作(我很想说SuperSed;-)
是一个正则表达式条件,它匹配任何一行,该行包含
——基本上是带有XML标记的任何行。相关操作是H
,它将行附加到“保持缓冲区”。另一个条件是
/\(Request\|Response\) XML/
当然,这是一个regexp,它匹配请求
或响应
,后跟空格,然后是XML
。相应的动作是
{s/^.*</</;x;p}
匹配输入的结尾,然后再次将保持缓冲区的内容交换到“打印缓冲区”中,然后打印它
您可以根据需要更改命令,例如,如果需要对不同的记录进行分隔,这将在它们之间放置一条空行:
sed -n '/^<.\+>/H; /\(Request\|Response\) XML/{s/^.*</\n</;x;p}; ${x;p}' xmllog
sed-n'/^/H/\(Request\| Response\)XML/{s/^.*听起来像是sed的工作(我很想说SuperSed;-)
是一个正则表达式条件,它匹配任何一行,该行包含
——基本上是带有XML标记的任何行。关联操作是H
,它将该行附加到“保持缓冲区”。另一个条件是
/\(Request\|Response\) XML/
当然,这是一个regexp,它匹配请求
或响应
,后跟空格,然后是XML
{s/^.*</</;x;p}
匹配输入的结尾,然后再次将保持缓冲区的内容交换到“打印缓冲区”中,然后打印它
您可以根据需要更改命令,例如,如果需要对不同的记录进行分隔,这将在它们之间放置一条空行:
sed -n '/^<.\+>/H; /\(Request\|Response\) XML/{s/^.*</\n</;x;p}; ${x;p}' xmllog
sed-n'/^/H;/\(请求\响应\)XML/{s/^.*没有理由不能用PHP来完成。当然,你不能将整个日志加载到内存中,你必须以流式方式扫描它。没有理由不能用PHP来完成。当然,你不能将整个日志加载到内存中,你必须以流式方式扫描它。我不是说我不想用合适的语言来完成,我只知道有时候你可以用内置工具拼凑出一些好东西:)如果这不可能,那么我将编写一些东西。我不是说我不想用合适的语言来编写,我只是知道有时候你可以用内置工具拼凑出一些好东西:)如果这不可能,那么我将编写一些东西漂亮、整洁、简单。我扩展了它,以便在有多个XML集的情况下将每个报告转储到一个文件中,但这已经足够让我开始了。在您的情况下,您可能需要编写$tag=qr/(?:RootTag | ResponseRoot)/;qr创建一个regexp和(?:…)这意味着括号没有捕获匹配项,也不是必需的,但使用它们可能是一种良好的做法。此外,这里的假设是,这两个标记仅用作各自XML片段的根(这很可能).Nice、neat和simple。我对其进行了扩展,以便在有多个XML集的情况下将每个报表转储到一个文件中,但这已经足够让我开始了。在您的情况下,您可能需要编写$tag=qr/(?:RootTag | ResponseRoot)/;qr创建一个regexp和(?:…)这意味着括号没有捕获匹配项,也不是必需的,但使用它们可能是一种良好的做法。此外,这里的假设是,这两个标记仅用作各自XML片段的根(很可能)。Real