Hi all,

I've written a Perl script below that check and report for malformed braces.
I have a UNIX ksh version and it took a couple of minutes to run on a 10000+
lines. With the Perl version it only took about 20 seconds so I decided to
do it the Perl way. Besides I need a similar thing for Windows as well at
some stage.

The sample output, script and the testfile01x.ora sample file are as below.

Just want to know if anyone have any advise on how to "improve" the code
somehow? The code works as it is the way I want it to but maybe there is a
better way arond it.

A short explanation of what the script does is as below:
- The script is run as check_malform.pl testfile01x.ora. testfile01x.ora is
the file to check for malformed braces
- The script remove all lines that begin with # and all blank lines
- It selects all lines that begins with an alphabetic character and place
its start and end into a tmp file
- It reads the tmp file and select some portions of the file and place these
lines in another tmp file.
- It checks the second tmp file and count the number of open ( and close )
braces
- If the number of open and close braces do not match, then it is reported
as MALFORMED

Main "improvement" that am hoping for is being able to read specific lines
of a a file just like the UNIX sed command.

I may want to expand the script at some stage to cover other malformed
characters, for example, < and >, { and }, [ and ] etc. but for now, am
happy with just ( and ).

http://pastebin.com/d8GNL0kx suggested by Jim GIBSON is very good but I
thought it would be fun and a very good learning experience to write
something of my own :-)

Any suggestion will be much appreciated. Thanks in advance.


============
Sample output of the run:
============

./check_malform.pl testfile01x.ora
Checking -> START = 1 :: END = 13 :: TNS = prod10.checks.com.ph = =
MALFORMed !!!
Checking -> START = 14 :: END = 26 :: TNS = prod11.checks.com.ph = = OKAY
Checking -> START = 27 :: END = 39 :: TNS = prod20.checks.com.ph = = OKAY
Checking -> START = 40 :: END = 52 :: TNS = devd11.checks.com.ph = =
MALFORMed !!!
Checking -> START = 53 :: END = 65 :: TNS = tstt11.checks.com.ph =  = OKAY
Checking -> START = 66 :: END = 78 :: TNS = devd1.checks.com.ph =  = OKAY
Checking -> START = 79 :: END = 87 :: TNS = quald_app.checks.com.ph = = OKAY
START  = Thu Jul 28 16:24:02 NZST 2011
FINISH = Thu Jul 28 16:24:02 NZST 2011

============
Code below:
============

#!/bin/perl -w
$start_run=`date`;
$fileTNS=$ARGV[0];

open(TNS, "< $fileTNS");
open(TMP01, "> ${fileTNS}.tmp.01");
open(TMP02, "> ${fileTNS}.tmp.02");

# -----------------------------------------------------------------------
# - Remove commented lines and blank line
# -----------------------------------------------------------------------
while (<TNS>) {
    next if /^#/;     # skip lines starting with comments
    next if /^$/; # blank lines
    print TMP01 $_;     # This is the line that we wanted
}
close TMP01;

# -----------------------------------------------------------------------
# - Search for lines that begins with alpha characters
# - This is where we get the range of lines for each entry
# -----------------------------------------------------------------------
$tns="";
$switch=0;
$count=0;
$start=0;
$end=0;
open(TMP01, "< ${fileTNS}.tmp.01");
while (<TMP01>) {
   $count++;
   if ( /^[a-z]/i ) {
      #print $_;
      if ( $switch eq 0 ) {
         $start=${count};
         $tns=$_;
         $switch=1;
      }
      elsif ( $switch eq 1 ) {
         $end=${count}-1;
         print TMP02 "${start},${end},$tns";
         ${start}=${count};
         $tns=$_;
      }
   }
   else {
      next;
   }
}
print TMP02 "${start},${count},${tns}";
close TMP02;
close TMP01;

# -----------------------------------------------------------------------
# - Now READ each range of lines and check if we have the
# - same number of opening and closing braces
# -----------------------------------------------------------------------
open(TMP02, "< ${fileTNS}.tmp.02");
open(MAL, "> ${fileTNS}.tmp.malformed");
while (<TMP02>) {
   chomp($_);
   my @tns_info = split(',', $_);

   $start_line=$tns_info[0];
   $end_line=$tns_info[1];
   $tns_line=$tns_info[2];

   my @tns = split('\.', $tns_line);

   #
-------------------------------------------------------------------------
   # - Print the range of lines that we want, i.e. $start_line TO $end_line
   #
-------------------------------------------------------------------------
   $count=0;
   open(TMP01, "< ${fileTNS}.tmp.01");
   open(TMP03, "> ${fileTNS}.tmp.03.$tns[0]");
   while (<TMP01>) {
      $count++;

      if ( ( ${count} >= ${start_line} ) && ( ${count} <= ${end_line} ) ) {
         print TMP03 $_;
      }

      last if ${count} > ${end_line};
   }
   close TMP01;
   close TMP03;

   my $count_open_brace;
   my $count_close_brace;
   my $count_open_brace_total;
   my $count_close_brace_total;
   open(TMP03, "< ${fileTNS}.tmp.03.$tns[0]");
   while (<TMP03>) {
      $count_open_brace  = ( $_ =~ tr/\(// );
      $count_close_brace = ( $_ =~ tr/\)// );
      $count_open_brace_total  += $count_open_brace;
      $count_close_brace_total += $count_close_brace;
   }
   close TMP03;

   if ( ${count_open_brace_total} == ${count_close_brace_total} ) {
      print "Checking -> START = $start_line :: END = $end_line :: TNS =
${tns_line} = OKAY \n";
   }
   else {
      print "Checking -> START = $start_line :: END = $end_line :: TNS =
${tns_line} = MALFORMed !!! \n";
      print MAL $tns_line . "\n";
   }
}
close MAL;
close TMP02;

print "START  = ${start_run}";
print "FINISH = " . `date`;
exit(0);

============
Test file to parse : testfile01x.ora
============

################
# Filename......: tnsnames.ora
# Name..........: LOCAL_REGION.world
# Date..........: 16 May 2007 - 10:15
################
prod10.checks.com.ph =
  (DESCRIPTION =
        (ADDRESS =
          (COMMUNITY = tcpip.world)
          (PROTOCOL = TCP)
          (Host = prod10)
          (Port = 25534)
        )
      (CONNECT_DATA =
        (SID = prod10)
           (GLOBAL_NAME = prod10.checks.com.ph)
      ))
  )

prod11.checks.com.ph =
  (DESCRIPTION =
        (ADDRESS =
          (COMMUNITY = tcpip.world)
          (PROTOCOL = TCP)
          (Host = prod15.checks.com.ph)
          (Port = 26467)
        )
      (CONNECT_DATA =
        (SID = prod15)
           (GLOBAL_NAME = prod15.checks.com.ph)
      )
 )
prod20.checks.com.ph =
  (DESCRIPTION =
        (ADDRESS =
          (COMMUNITY = tcpip.world)
          (PROTOCOL = TCP)
          (Host = prod20)
          (Port = 25535)
        )
      (CONNECT_DATA =
        (SID = prod20)
           (GLOBAL_NAME = prod20.checks.com.ph)
      )
  )
devd11.checks.com.ph =
  (DESCRIPTION =
        (ADDRESS =
          (COMMUNITY = tcpip.world)
          (PROTOCOL = TCP)
          (Host = devd11.checks.com.ph)
          (Port = 26465)
        )
      ((CONNECT_DATA =
        (SID = devd11)
           (GLOBAL_NAME = devd11.checks.com.ph)
      )
 )
tstt11.checks.com.ph =
  (DESCRIPTION =
        (ADDRESS =
          (COMMUNITY = tcpip.world)
          (PROTOCOL = TCP)
          (Host = tstt11)
          (Port = 30007)
        )
      (CONNECT_DATA =
        (SID = tstt11)
           (GLOBAL_NAME = tstt11.checks.com.ph)
      )
  )
devd1.checks.com.ph =
  (DESCRIPTION =
        (ADDRESS =
          (COMMUNITY = tcpip.world)
          (PROTOCOL = TCP)
          (Host = devd1)
          (Port = 30023)
        )
      (CONNECT_DATA =
        (SID = devd1)
           (GLOBAL_NAME = devd1.checks.com.ph)
      )
  )
quald_app.checks.com.ph =
  (DESCRIPTION =
    (ADDRESS_LIST = (LOAD_BALANCE=on)(FAILOVER=on)
      (ADDRESS = (PROTOCOL = TCP)(HOST=quald1.checks.com.ph)(PORT = 1528))
      (ADDRESS = (PROTOCOL = TCP)(HOST=quald2.checks.com.ph)(PORT = 1528))
      (ADDRESS = (PROTOCOL = TCP)(HOST=quald3.checks.com.ph)(PORT = 1528))
    )
    (CONNECT_DATA=(SERVICE_NAME=quald_app.checks.com.ph))
  )

Reply via email to