1

I have a log file which contains an output of several commands run on each server. The format is like

APRHY01> lt all
131119-15:41:39 10.105.219.68 10.0b  stopfile=/tmp/27599
Checking MOM version...RNC_NODE_MODEL_M_1_200
Parsing MOM (cached): /home/ekisjay/moshell//jarxml/RNC_NODE_MODEL_M_1_200.xml.cache.gz Done.
.............
.
.
.
APRHY01> alt
131119-15:41:55 10.105.219.68 10.0b RNC_NODE_MODEL_M_1_200 stopfile=/tmp/27599
Connecting to 10.105.219.68:56834 (CorbaSecurity=OFF, corba_class=2, java=1.6.0_26, jacoms=R73D19, jacorb=R73D01)
Starting to retrieve active alarms
Nr of active alarms are: 3

APRHY01> strt
131119-15:41:58 10.105.219.68 10.0b RNC_NODE_MODEL_M_1_200 stopfile=/tmp/27599

Following 326 sites are up:
---------------------------------------------------------------------------------------------------------------------
 MOD  IUBLINK    CELLNAMES        CFRPHEM1 CFRPHEM2 CFRPHEM3 CFRPHEM4 CFRPHEM5 CFRPHEM6 ICDS   TN ATMPORTS
---------------------------------------------------------------------------------------------------------------------
  21  Iub_00023  UHYD494-X        111111                                                1  1    I
  21  Iub_00032  UHY4100-X        111111                                                1  1    I

then for next server or node this repeats...

APRHY02> lt all

131119-15:44:51 10.105.219.4 10.0b  stopfile=/tmp/2874
Checking MOM version...RNC_NODE_MODEL_M_1_200
Parsing MOM (cached): /home/ekisjay/moshell//jarxml/RNC_NODE_MODEL_M_1_200.xml.cache.gz Done.
Using paramfile /home/ekisjay/moshell//commonjars/pm/PARAM_RNC_M_1_50.txt
Parsing
 file /home/ekisjay/moshell//commonjars/pm/PARAM_RNC_M_1_50.txt ...

I have to take few lines (according to the conditons that are said in the requirement) between every command for each node. I wrote a perl program in reading through line by line and stop at every line that matches a command like /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\> and then retrieve the required lines between and upto the next command line and write it to another file. In the loop, my program actually skips one command in between and goes for the next command (1st, 3rd, 5th kind of...). Can anyone help me?

3 Answers 3

0

Perhaps the following will be helpful:

use strict;
use warnings;

my ( $fileName, $fh, $i );

while (<>) {
    if ( !$fileName or $fileName ne $ARGV ) {
        $fileName = $ARGV;
        $i        = 0;
    }

    if ( my ($cmd) = /^([A-Z]{5}\d{2}>.+)/ ) {
        $cmd =~ s/\W+/_/g;
        open $fh, '>', $cmd . '_' . ( sprintf '%05d', ++$i ) . '.txt' or die $!;
    }

    print $fh $_;
}

Command-line usage: >perl script.pl logFile1 [logFile2 .. logFileN]

The [ ] notation indicates optional, multiple files.

The script uses a regex to capture the command/server line, then substitutes 'non-word' characters with an underscore, and this plus a count plus .txt becomes the file name to which that block of command text is written. Thus, using your dataset, the following text files were created containing command content:

APRHY01_lt_all_00001.txt
APRHY01_alt_00002.txt
APRHY01_strt_00003.txt
APRHY02_lt_all_00001.txt
APRHY02_alt_00002.txt
APRHY02_strt_00003.txt

The count was inserted just in case the same command was issued more than once to the same server, as this number insures separate files for each.

Sign up to request clarification or add additional context in comments.

Comments

0

You haven't showed us the code you're using to parse the file, so it's hard to say what might be wrong with it :-)

For breaking down multi-line log output like this, a good method is to loop through the file, appending lines to a block of text, until you find the first line of the next block -- then flush the block you've been appending and create a new one, starting with the current line.

my $block = "";
while (<>) {
    if (/[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/) {
        write_block($block) if $block;
        $block = "";
    }
    $block .= $_;
}
write_block($block);

4 Comments

code: my $srcFile = "new.log";my $destFile = "deviations.log";my grabbed = {};my $line = "";open (my $src, "$srcFile") or die "Could not open the log file $srcFile: $!";open (my $dest, ">>$destFile") or die "Could not open the destination file $destFile: $!";while ($line = <$src>){ if ($line =~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/) { push grabbed, "Deviations of the output of command: $line\n"; while ($line = <$src>){if ($line !~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/){push grabbed, $line;}else{last;}}}}print $dest "\ngrabbed";close $dest;close $src;
Please consider adding the code to the original question, for the benefit of anyone else reading who is trying to answer. And please copy and paste exactly the code that you are having trouble with, to make sure that the problem isn't confused by any transcription mistakes (like grabbed for $grabbed).
When your script encounters the first line of the file, a match will occur and a null string will be passed to write_block().
@kenosis Fair enough, that's easy to get around by checking to see that $block evaluates to true.
0

Your

code:

my $srcFile = "new.log";
my $destFile = "deviations.log";
my @grabbed = {};
my $line = "";
open (my $src, "$srcFile") or die "Could not open the log file $srcFile: $!";
open (my $dest, ">>$destFile") or die "Could not open the destination file $destFile: $!";
while ($line = <$src>)
{ if ($line =~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/)
  { push @grabbed, "Deviations of the output of command: $line\n";
    while ($line = <$src>)
    {if ($line !~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/)
     {push @grabbed, $line;
     }
     else
     {last;
} } }}
print $dest "\n@grabbed";
close $dest;
close $src;

when executing last on finding a new command line, goes to the outer while ($line = <$src>), thereby already reading the next line (the first output line of the command) and failing to recognize the start of the command. A simple fix is to omit the reading of a new line by labeling the outer loop and using redo instead of last:

LINE:
while ($line = <$src>)
{ if ($line =~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/)
  { push @grabbed, "Deviations of the output of command: $line\n";
    while ($line = <$src>)
    { if ($line !~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/)
      { push @grabbed, $line }
      else
      { redo LINE }
} } }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.