如何从特定行读取到另一行 - Perl
How to read from specific line to another line - Perl
我正在执行一个 Perl 脚本,我有一个日志文件,我需要从中提取数据。我想知道如何从特定行读取到另一行(不是文件末尾)。
我尝试过这种方式,如果它到达我想要停止的行但它不起作用,则放置 last if
。我要开始阅读的行是 <TEST_HEAD TH 1>
并在 </TEST_HEAD TH 1>
处停止。我这样做是因为我的正则表达式捕获了我不需要的数据,所以我尝试从特定行读取到另一行。
这是我到目前为止所做的:
while(<$log_fh>)
{
if($. =~ /\<TEST_HEAD TH 1\>/)
{
if ( /Computer Name:\s*(\S+)(-\d+)/i )
{
$details{tester_name} = . ;
$details{tester_type} = ;
push @{$details{tester_arr}}, . ;
}
elsif ( /Operating System:\s*(.*\S)/i )
{
$details{op_sys} = ;
}
elsif ( /IG-XL Version:\s*([^;]*)/i )
{
$details{igxl_vn} = ;
}
elsif ( /^([\d]+)\.\d\s+(\S+)\s+([\d-]*)\s+([\d|\w]*)(?=\s)/ )
{
push @{$details{slot}}, ;
push @{$details{board_name}}, ;
push @{$details{part_no}}, ;
push @{$details{serial_no}}, ;
}
last if $. == /\<\/TEST_HEAD TH 1\>/;
}
}
原始数据文件的修改样本:
<TEST_HEAD TH 1> #Start reading here
(Lines containing data to be captured)
</TEST_HEAD TH 1> #end reading here
在不深入了解嵌套匹配逻辑的情况下,您可能想要更改
if($. =~ /\<TEST_HEAD TH 1\>/)
进入
if (/<TEST_HEAD TH 1>/ .. /<\/TEST_HEAD TH 1>/)
你问的实际上是XY问题,最好用xml解析器处理xml like document。 Parsing complex XML in Perl
在不知道您的数据具体如何的情况下,我还提供了另一种方法。
将$/
设置为记录分隔符,然后您就可以一次性抓取一大块文本。然后,您可以一次对它应用一堆不同的正则表达式。
例如:
local $/ = 'TEST_HEAD';
while (<$log_fh>) {
next unless m/^\s*TH/;
my ( $tester_name, $tester_id ) = (m/Computer Name:\s*(\S+)(-\d+)/i);
my ($op_sys) = (m/Operating System:\s*(.*\S)/i);
my ( $slot, $board, $part, $serial ) =
(m/^([\d]+)\.\d\s+(\S+)\s+([\d-]*)\s+([\d|\w]*)(?=\s)/m);
# etc.
# then validate and update your array:
$details{$tester_name} = $tester_name;
## etc.
}
我正在执行一个 Perl 脚本,我有一个日志文件,我需要从中提取数据。我想知道如何从特定行读取到另一行(不是文件末尾)。
我尝试过这种方式,如果它到达我想要停止的行但它不起作用,则放置 last if
。我要开始阅读的行是 <TEST_HEAD TH 1>
并在 </TEST_HEAD TH 1>
处停止。我这样做是因为我的正则表达式捕获了我不需要的数据,所以我尝试从特定行读取到另一行。
这是我到目前为止所做的:
while(<$log_fh>)
{
if($. =~ /\<TEST_HEAD TH 1\>/)
{
if ( /Computer Name:\s*(\S+)(-\d+)/i )
{
$details{tester_name} = . ;
$details{tester_type} = ;
push @{$details{tester_arr}}, . ;
}
elsif ( /Operating System:\s*(.*\S)/i )
{
$details{op_sys} = ;
}
elsif ( /IG-XL Version:\s*([^;]*)/i )
{
$details{igxl_vn} = ;
}
elsif ( /^([\d]+)\.\d\s+(\S+)\s+([\d-]*)\s+([\d|\w]*)(?=\s)/ )
{
push @{$details{slot}}, ;
push @{$details{board_name}}, ;
push @{$details{part_no}}, ;
push @{$details{serial_no}}, ;
}
last if $. == /\<\/TEST_HEAD TH 1\>/;
}
}
原始数据文件的修改样本:
<TEST_HEAD TH 1> #Start reading here
(Lines containing data to be captured)
</TEST_HEAD TH 1> #end reading here
在不深入了解嵌套匹配逻辑的情况下,您可能想要更改
if($. =~ /\<TEST_HEAD TH 1\>/)
进入
if (/<TEST_HEAD TH 1>/ .. /<\/TEST_HEAD TH 1>/)
你问的实际上是XY问题,最好用xml解析器处理xml like document。 Parsing complex XML in Perl
在不知道您的数据具体如何的情况下,我还提供了另一种方法。
将$/
设置为记录分隔符,然后您就可以一次性抓取一大块文本。然后,您可以一次对它应用一堆不同的正则表达式。
例如:
local $/ = 'TEST_HEAD';
while (<$log_fh>) {
next unless m/^\s*TH/;
my ( $tester_name, $tester_id ) = (m/Computer Name:\s*(\S+)(-\d+)/i);
my ($op_sys) = (m/Operating System:\s*(.*\S)/i);
my ( $slot, $board, $part, $serial ) =
(m/^([\d]+)\.\d\s+(\S+)\s+([\d-]*)\s+([\d|\w]*)(?=\s)/m);
# etc.
# then validate and update your array:
$details{$tester_name} = $tester_name;
## etc.
}