我有一个日志文件内容很多 block /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)
来检查每个 block 并仅在关键字之后提取数据
#!/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': $!";
但是执行后我什么也没得到。有人可以向我推荐示例想法吗?
最佳答案
大多数内容看起来都不错,但正是您的启动正则表达式导致了第一个问题:
'^\/begin CHECK\n\n'
您正在从文件中读取行,然后查找连续的两个换行符。这永远不会匹配,因为一行恰好以一个换行符结束(除非您更改 $/
,但这是一个不同的主题)。如果要匹配一行的发送,可以使用$
(或 \z
) anchor :
'^\/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
已完成。
关于perl - 从分隔 block 中解析数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51947225/