Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi, This is my piece of code-
my $logFile = $ARGV[0]; die "usage: $0 <logFile>" unless $logFile; die "Logfile $logFile doesn't exist" unless -f "$logFile"; open(my $log, "<", $logFile) or die "Can't open $logFile for reading." +; print "Processing file $logFile...\n"; #my $authenticates = {}; my $n = 0; my $ArcotIDError_Count = 0; my $QnAError_Count = 0; my $UPError_Count = 0; my $OTPError_Count = 0; my $errorCode; while(my $line = <$log>) { $n++; $line =~ tr/\r\n//d; if($line =~ /Handling NSPAdvice for mechanism [4]/) { while ( $line = <$log> ) { if ($line =~ /Authentication mechanism returned [[](\S*)[] +]/) { my $errorCode = $1; print $errorCode; if ($errorCode != 0 || $errorCode != 1) { $ArcotIDError_Count++; } } next; } } } print "Total Number Of ArcotID Authentication ErrorCode returned i +s $ArcotIDError_Count\n";
I am counting the error code for Mechanism4. But it is not giving me the desired output,instead it prints 0. Here is the snippet of the logfile-
Handle_NSPAdvice:: Handling NSPAdvice for mechanism [4] Fri May 29 18:39:05.217 2009 Morocco Standard Time INFO: pid 3216 t +id 2592: 170: 133090: Handle_NSPAdvice::NSP Action :[NSP_INC] Fri May 29 18:39:05.217 2009 Morocco Standard Time INFO: pid 3216 t +id 2592: 170: 133090: Using Oracle Query Fri May 29 18:39:05.217 2009 Morocco Standard Time INFO: pid 3216 t +id 2592: 170: 133090: NSP Update Query is based on Serial Number Fri May 29 18:39:05.232 2009 Morocco Standard Time INFO: pid 3216 t +id 2592: 17: 133090: ArAuthFrameworkImpl::doPostAuth::11:133088:: Aut +hentication mechanism returned [3] for AuthIdentity [01246825]
Thanks NT

Replies are listed 'Best First'.
Re: not getting desired output
by ikegami (Patriarch) on Jun 11, 2009 at 15:41 UTC

    Problems:

    • /[4]/ matches "4", not "[4]".

    • You never exit the inner loop before the end of the file.

    • $errorCode != 0 || $errorCode != 1
      should be
      $errorCode != 0 && $errorCode != 1
      The former is always true.

    • die ... unless -f "$logFile"; is useless, even harmful. open not only performs this check, but can provide a better error message.

    • You call <> (in the outer loop) after being told you've reached the end of the file (in the inner loop).

    • \[ is more usual and readable than [[]
      \] is more usual and readable than []]

    • while (...) { ...; next }
      is the same as just
      while (...) { ...; }

    Fix:

    use strict; use warnings; my $ArcotIDError_Count = 0; OUTER: while(my $line = <>) { $line =~ tr/\r\n//d; next if $line !~ /Handling NSPAdvice for mechanism \[4\]/; do { $line = <>; last OUTER if !defined($line); } while $line !~ /Authentication mechanism returned \[(\d+)\]/; my $errorCode = $1; #print("\$errorCode=$errorCode\n"); if ($errorCode != 0 && $errorCode != 1) { $ArcotIDError_Count++; } } print "Total Number Of ArcotID Authentication ErrorCode returned is $A +rcotIDError_Count\n";

    ( I see that others have identified some of the issues, but not all. )

    Update: Reordered points by descending severity.

      Hi, Sorry, i am getting diffrent output when i run Ikegami script and my script with chnages. I am getting 142 for Ikegami and 352 for my script. Thanks NT

        Like I said, the other monks only found some of the problems in your script. Your script counts errors that aren't for "Handling NSPAdvice for mechanism [4]".

        For example, for the following log, your script counts two errors and mine counts one:

        ...Handling NSPAdvice for mechanism [4]... ...Authentication mechanism returned [3]... ...Handling NSPAdvice for mechanism [5]... ...Authentication mechanism returned [3]...

        This is a symptom of your inner loop not exiting before the end of the log file (the second bullet in the grandparent post).

        Maybe \d+ is too restrictive? If you can have negative numbers, change it to -?\d+
      Hi , I got it. You guys are wonderful. Thanks NT
Re: not getting desired output
by jwkrahn (Abbot) on Jun 11, 2009 at 15:30 UTC

    You need to change:

    if($line =~ /Handling NSPAdvice for mechanism [4]/) {

    to

    if($line =~ /Handling NSPAdvice for mechanism \[4\]/) {

    because the character [ is special in a regular expression.

    Update: Your logic in the statement:

    if ($errorCode != 0 || $errorCode != 1) {

    is flawed because an $errorCode with any number will pass this test.   You probably meant:

    if ($errorCode != 0 && $errorCode != 1) {
      Hi , Thanks for your reply, that part got reolved, but i am not getting the desired output. I need to count all except 0 and 1 for mechanism, but in the output file, i can see all are printed and counted.Some logic problem i guess. Please suggest me what i am doing wrong. Thanks NT
Re: not getting desired output
by Perlbotics (Archbishop) on Jun 11, 2009 at 15:38 UTC

    You need to escape the square brackets since you want to match a literal [4], so instead of

    if($line =~ /Handling NSPAdvice for mechanism [4]/) { # the RE above would match "Handling NSPAdvice for mechanism 4"
    try this:
    if($line =~ /Handling NSPAdvice for mechanism \[4\]/) { # alternative: if ( index($line,'Handling NSPAdvice for mechanism +[4]')>=0 ) {
    Analogue:
    if ($line =~ /Authentication mechanism returned [[](\S*)[] +]/) {
    ...to...
    if ($line =~ /Authentication mechanism returned \[(\-?\d+) +\]/) { # the RE above would match e.g. [4] -> $1=4, [-10] -> $1= +-10, etc.
    HTH

Re: not getting desired output
by lostjimmy (Chaplain) on Jun 11, 2009 at 15:40 UTC

    jwkrahn's suggestion fixes your problem, but might I also suggest you change your second regex? It's difficult to read for what it does.

    $line =~ /Authentication mechanism returned \[(\d+)\]/

    OK, so it's not that much easier to read...

Re: not getting desired output
by Marshall (Canon) on Jun 11, 2009 at 22:28 UTC
    I see a number of things that could be improved here. Ikegami listed more below and quite correctly so.
    For now, I'll just address the first part of "how to start".

    The first thing is to determine whether or not we have the right number of arguments. In Perl this the number of elements in @ARGV.

    Then normally statement(s) follow that assign the @ARGV elements to $scalar values.

    Then these values are used. Update: to open file(s)

    This is a general "formula or pattern" for your Perl programs.

    #!/usr/bin/perl -w use strict; #my $logFile = $ARGV[0]; #die "usage: $0 <logFile>" unless $logFile; #die "Logfile $logFile doesn't exist" unless -f "$logFile"; #open(my $log, "<", $logFile) or die "Can't open $logFile for reading. +" die "Wrong number of args\nUsage: $0 Logfile" if (@ARGV != 1); my ($logFile) = @ARGV; open(my $log, "<", $logFile) || die "Can't open $logFile for reading";