【问题标题】:Extracting certain pattern from log从日志中提取特定模式
【发布时间】:2010-11-12 04:56:15
【问题描述】:

我需要从如下所示的日志文件中提取请求:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vehicleRegistration>
.... XML in between ....
.... XML in between ....
.... XML in between ....
.... XML in between ....
... at nth line there is line like this <vehicle id="2312313"></vehicle>
.... XML in between ....
.... XML in between ....
</vehicleRegistration>

重要的问题是vehicleRegistration 可以是5 行,有时是17 行,它是可变的。这是我当前的 grep 失败的地方,我使用了:

grep -A 13 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" vehicle.log

另一个问题是,有时一个请求可能会被发送 2 次或更多次,因为该服务可能由于某种原因不可用,因此文件中可能存在相同的多个请求。

我还应该排除重复请求,通过比较第 n 行(不是最后一行)&lt;vehicle id="2312313"&gt;&lt;/vehicle&gt;,如果车辆 id 重复而不是重复,则可以知道请求是重复的。

你会用什么方法来解决这个问题?建议,代码,伪代码,任何东西都欢迎。

编辑:

日志文件不是 xml 文件,它只是一个包含一小部分 xml 请求的文件,我无法将其解析为 XML

编辑二:

我只提取了车辆注册部分,使用@eugene y 一行命令perl -nle 'm{&lt;vehicleRegistration&gt;} .. m{&lt;/vehicleRegistration&gt;} and print' logfile ,我怎样才能摆脱重复,那些具有相同车辆id的节点,我只想保留一个副本。

【问题讨论】:

    标签: perl unix sed awk grep


    【解决方案1】:

    我会使用XML::Simple(或其他 XML 解析器)来提取数据。 Data::Dumper 可用于检查数据结构。

    更新:您可以像这样提取vehicleRegistration 元素:

    open my $fh, '<', 'logfile' or die $!;     
    my $xml = ""; 
    
    while (<$fh>) {
        if ( m{<vehicleRegistration>} .. m{</vehicleRegistration>}) {
            $xml .= $_; 
        }   
    }
    

    或者使用 perl 单行:

    perl -nle 'm{<vehicleRegistration>} .. m{</vehicleRegistration>} and print' logfile
    

    【讨论】:

    • 我刚刚编辑了我的问题,日志文件不是 xml 文件,它只包含一些请求,所以我无法将其解析为 xml
    • @c0mrade - 这些 XML sn-ps 是如何分离的?你能提取这些 XML 块并按照 eugene 的建议进行解析吗?
    • @eumiro @eugene y 是的,我已经分离了 XML 部分,如何去除重复项?
    • @c0mrade - 将结果通过管道传送到 sort 和 uniq,i。 e. sort | uniq -d
    • @Luca Martini 当车辆 ID 重复时我想摆脱整个 之间的任何内容
    【解决方案2】:

    在 unix 中使用 awk 或 gawk 命令提取注册...

    #!/usr/bin/awk -f 
    
    /^<vehicleRegistration>/ { printit="true" } # set the print flag on
    printit ~ "true" { print }                  # if printflag set print
    /^</vehicleRegistration>{ printit="false" } # turn print flag off
    

    【讨论】:

      【解决方案3】:

      使用XPath 恢复 XML 元素节点。有许多适用于各种现代脚本语言的框架。

      使用 Perl,您可能会执行以下操作:

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      use XML::XPath;
      
      my $file = 'vehicleRegistration.xml';
      my $xp = XML::XPath->new(filename => $file);
      
      print "Vehicle id: ".$xp->find('//vehicle/@id')."\n";
      

      如果需要,请解析日志文件以提取 XML 文档部分,然后对其运行 XPath 表达式以恢复所需的元素和数据。

      【讨论】:

      • 谢谢你的回复,上面这个是做什么的?打印车辆ID?我需要使用此车辆 ID 来摆脱整个 之间的任何内容
      • 是的,这会获取您已删除的 XML 块并打印出车辆 ID。
      • 我想删除与其他任何 vehicleRegistration 节点包含相同车辆 ID 的车辆注册节点,我会这样做吗?伪代码或代码会很棒,或者教程或任何可能帮助我完成这项工作的东西。 tnx
      • 保留一个哈希表 (%registrations),它使用车辆 ID 作为键。如果没有与车辆 ID 键关联的值,则添加 vehicleRegistration 节点作为值 (if (! defined $registrations{$vehicleId}) { $registrations{$vehicleId} = $regXmlValue; })。如果车辆 ID 密钥有值,请继续。最后,读出与唯一车辆 ID (foreach $id (sort keys %registrations) { print $registrations{$id}; } ) 关联的车辆注册节点列表的哈希表。 HTH。
      【解决方案4】:

      使用XPath(并且取决于您想要对结果做什么,可能是Xslt)

      有这方面的命令行实用程序,here, for example

      【讨论】:

      • 对不起,我刚刚编辑了我的问题,日志文件不是 xml 文件,它只包含一些请求,所以我无法将其解析为 xml
      • 当然可以 :) 提取 和 之间的文本并将其传递给 XML 解析器...
      猜你喜欢
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 2021-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多