kross
kross

Reputation: 475

How to read from specific line to another line - Perl

I'm doing a Perl script and I have a log file where I need to extract data from. I want to know how to read from a specific line to another line(not end of file).

I tried it this way by putting a last if if it reaches the line that I want to stop at but it doesn't work. The line that I want to start reading from is <TEST_HEAD TH 1> and stops at </TEST_HEAD TH 1>. I'm doing this because my regular expression captures data that I do not need, so I tried to read from a specific line to another line.

This is what I've done so far:

while(<$log_fh>)
{
    if($. =~ /\<TEST_HEAD TH 1\>/)
    {
      if ( /Computer Name:\s*(\S+)(-\d+)/i )
      {
          $details{tester_name} = $1 . $2;
          $details{tester_type} = $1;
          push @{$details{tester_arr}}, $1 . $2;
      }
      elsif ( /Operating System:\s*(.*\S)/i )
      {
          $details{op_sys} = $1;
      }
      elsif ( /IG-XL Version:\s*([^;]*)/i )
      {
          $details{igxl_vn} = $1;
      }
      elsif ( /^([\d]+)\.\d\s+(\S+)\s+([\d-]*)\s+([\d|\w]*)(?=\s)/ )
      {
          push @{$details{slot}}, $1;
          push @{$details{board_name}},  $2;
          push @{$details{part_no}},  $3;
          push @{$details{serial_no}},  $4;
      }
      last if $. == /\<\/TEST_HEAD TH 1\>/;
    }
}

Just a modified sample of the raw data file:

<TEST_HEAD TH 1> #Start reading here

    (Lines containing data to be captured)

</TEST_HEAD TH 1> #end reading here

Upvotes: 0

Views: 354

Answers (2)

Sobrique
Sobrique

Reputation: 53478

Without knowing specifically how your data looks, I'd also offer another approach.

Set $/ to a record separator, and then you grab a chunk of text in one go. You can then apply a bunch of different regexes to it all at once.

E.g.:

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.
}

Upvotes: 0

mpapec
mpapec

Reputation: 50637

Without going much into the nested matching logic you may want to change

if($. =~ /\<TEST_HEAD TH 1\>/)

into

if (/<TEST_HEAD TH 1>/ .. /<\/TEST_HEAD TH 1>/)

What you ask is actually XY problem and it would be better to process xml like document with xml parser. Parsing complex XML in Perl

Upvotes: 2

Related Questions