首页 > 解决方案 > 从分隔块解析数据

问题描述

我有一个日志文件内容很多块/begin CHECK....../end CHECK如下所示:

/begin CHECK

Var_AAA
"Description AAA"
DATATYPE UBYTE
Max_Value 255.
ADDRESS 0xFF0011

/end CHECK

/begin CHECK

Var_BBB
"Description BBB"
DATATYPE UBYTE
Max_Value 255.
ADDRESS 0xFF0022

/end CHECK
...

我想提取变量名及其地址,然后像这样写入一个新文件

Name    Address
Var_AAA => 0xFF0011
Var_BBB => 0xFF0022

我只是在考虑($start, $keyword, $end)检查每个块并仅在关键字之后提取数据

#!/usr/bin/perl

use strict;
use warnings;

my $input  = 'input.log';
my $output = 'output.out';

my ( $start, $keyword, $end ) = ( '^\/begin CHECK\n\n', 'ADDRESS ', '\/end CHECK' );
my @block;

# open input file for reading
open( my $in, '<', $input ) or die "Cannot open file '$input' for reading: $!";

# open destination file for writing
open( my $out, '>', $output ) or die "Cannot open file '$output' for writing: $!";

print( "copying variable name and it's address from $input to $output \n" );

while ( $in ) {    #For each line of input

    if ( /$start/i .. /$end/i ) {    #Block matching
        push @block, $_;
    }

    if ( /$end/i ) {

        for ( @block ) {

            if ( /\s+ $keyword/ ) {
                print $out join( '', @block );
                last;
            }
        }

        @block = ();
    }

    close $in or die "Cannot close file '$input': $!";
}

close $out or die "Cannot close file '$output': $!";

但执行后我什么也没得到。任何人都可以建议我的示例想法吗?

标签: stringperlparsing

解决方案


大多数东西看起来都不错,但它是你的开始正则表达式导致了第一个问题:

'^\/begin CHECK\n\n'

您正在从文件中读取行,然后连续查找两个换行符。这永远不会匹配,因为一行以一个换行符结尾(除非您更改$/,但这是一个不同的主题)。如果要匹配行的发送,可以使用$(或\z)锚:

'^\/begin CHECK$'

这是我精简的程序。您可以对其进行调整以完成您需要做的所有其他事情:

use v5.10;
use strict;
use warnings;

use Data::Dumper;

my ($start, $keyword, $end) = (qr{^/begin CHECK$}, qr(^ADDRESS ), qr(^/end CHECK));

while (<DATA>) #For each line of input
{
    state @block;
    chomp;
    if (/$start/i .. /$end/i) #Block matching
    {
        push @block, $_ unless /^\s*$/;
    }

    if( /$end/i )
    {
        print Dumper( \@block );
        @block = ();
    }
}

之后,您将不再读取数据。您需要将文件句柄放在里面<>(行输入运算符):

 while ( <$in> )

文件句柄将在程序结束时自动关闭。如果您想自己关闭它们,那很好,但在完成之前不要这样做。$in在完成之前不要关闭while


推荐阅读