Search between pattrens with one string in one or other line........

Hi have a lots of files with this type of code

Example--1
PROCEDURE DIVISION USING

AAA
BBB
CCC.

Example--2

PROCEDURE DIVISION
Some Commented Lines....
USING

AAA
BBB
CCC.

Example--3
PROCEDURE DIVISION
USING

AAA
BBB
CCC
.

Basically the word USING can be in same line as PROCDURE DIVISION or on next line or on the next after a commnet

I want to count no.of arguments between PROCEDURE DIVISION followed by USING (in the same line or next line) and "." (same thing over here "." can be in the same line as last argument or in a new line)

I wanted to find the no.of arguments each file uses...

something to start with:

nawk -f pb.awk myFile

pb.awk:
BEGIN {
  FS=RS=""
}
$1 ~ "^PROCEDURE DIVISION" {
  block=1
  next
}
block {
  block=0
  n=split($0,a)
  printf("FILENAME->[%s] n=%d\n", FILENAME, a[n]!="."?n:n-1)
}
# !/opt/third-party/bin/perl

open(FILE, "<", "p");

while(<FILE>) {
  if( /using/i ) {
    $start = 1;
    next;
  }
  if ( /\./ ) {
    $start = 0;
    $cnt++ if( !/^\./ );
  }
  next if( /^$/ );
  $cnt++ if( $start == 1 );
}

close(FILE);

print "count: $cnt\n";

exit 0

Try the following awk program :

#!/usr/bin/awk -f
# Awk File : cbl_args.awk

function print_args_count() {
   if (file) print file," #Args=" args_count;
}

FNR==1  {
   print_args_count();
   file         = FILENAME;
   proceed_args = 0;
   args_count   = 0;
}

/^[[:space:]]*\*/ {
   next; # skip comment
}

/PROCEDURE DIVISION/,/\./ {
   if ($0 ~ /USING/) {
      proceed_args=1;
      next;
   }
   if ($0 ~ /^[[:space:]]*\./) next;
   if (proceed_args && NF>0) ++args_count;
}

END {
   print_args_count();
}

Input Files :

$ cat pgm0.cbl
*
PROCEDURE DIVISION
.
*
$ cat pgm1.cbl
*
PROCEDURE DIVISION USING

CCC.
*
$ cat pgm2.cbl
*
PROCEDURE DIVISION 
* Some Commented Lines....
USING

BBB
CCC.
*
$ cat pgm3.cbl
*
PROCEDURE DIVISION 
USING

AAA
BBB
CCC
.
*
$ 

Output:

$ awk -f cbl_args.awk *.cbl
pgm0.cbl  #Args=0
pgm1.cbl  #Args=1
pgm2.cbl  #Args=2
pgm3.cbl  #Args=3
$

Jean-Pierre.

Jean-Pierre that was AWESOME....

I would be very very thankfull if u can take the pain of explaining the code...

thanks in advance.....

Sorry

but small change ..

there is also a case where we have

PROCEDURE DIVISION USING AAA BBB. (In this case it Fails)

And One more....

after USING we have Comments in few cases... like

PROCEDURE DIVISION    

Some Comments...
USING
Some Comments
AAA
BBB
.

For the Second case i have added a line (May be wrong)

/PROCEDURE DIVISION/,/\./ {
if ($0 ~ /USING/) {
proceed_args=1;
next;
}
if ($0 ~ /^[[:space:]]\./) next;
if ($0 ~ /^[[:space:]]*\
/) next; (Thought it will skip for "*")
if (proceed_args && NF>0) ++args_count;
}

Comments are already ignored.

I have rewritten the central part of the awk program to handle all cases (i hope) :

#!/usr/bin/awk -f
# Awk File : cbl_args.awk

function print_args_count() {
   if (file) print file," #Args=" args_count;
}

FNR==1  {
   print_args_count();
   file         = FILENAME;
   proceed_args = 0;
   args_count   = 0;
}

/^[[:space:]]*\*/ {
   next; # skip comment
}

/PROCEDURE DIVISION/,/\./ {
   count = NF;
   if (/PROCEDURE DIVISION/) count -= 2;
   if (/USING/) {
      proceed_args=1;
      --count;
   }
   if (NF == ".") --count;
   if (proceed_args) args_count += count;
}

END {
   print_args_count();
}

and add some modifications to my input files and create new ones :

$ cat pgm3.cbl
*
PROCEDURE DIVISION
USING

AAA BBB
CCC
.
*

$ cat pgm4.cbl
PROCEDURE DIVISION USING AAA BBB CCC DDD.
$ cat pgm5.cbl

PROCEDURE DIVISION USING
    AAA
    BBB
    CCC
    DDD
    EEE. 
$

The output :

$ awk -f cbl_args.awk pgm*.cbl
pgm0.cbl  #Args=0
pgm1.cbl  #Args=1
pgm2.cbl  #Args=2
pgm3.cbl  #Args=4
pgm4.cbl  #Args=4
pgm5.cbl  #Args=5
$

Jean-Pierre.


  1. [:space:] ↩︎

  2. [:space:] ↩︎

[quote=aigles]
Comments are already ignored.

I have Something of this sort which fails

I2OCR *PROCEDURE DIVISION USING XXXXXX
PROCEDURE DIVISION
CHANGE FOR ENDS
USING
CHANGE FOR BEGINS
AAAA
BBBBB
CCCC
DDDD
EEEE
FFFF
GGGG
.

My awk script assume that comments lines start with * as first non blank character. That is not the case for your file since the comment line start with I2OCR.
I have modified my awk program to remove from input lines all chars from the first * to the end of line.

#!/usr/bin/awk -f
# Awk File : cbl_args.awk

function print_args_count() {# Function for printing filename and arguments count 
   if (file)                 # Only if file name is set.
      print file," #Args=" args_count;
}

FNR==1  {              # New input file
   print_args_count();       # Print argument count for previus file
   file         = FILENAME;  # Memorize the file name
   proceed_args = 0;         # Reset flag 'USING' keyword found, args coming..
   args_count   = 0;         # Reset arguments count
}

{                            # For all input lines
   sub(/\*.*$/, "");         # Removes comments (all chars from first * to end of line)
}

/PROCEDURE DIVISION/,/\./ {  # For lines from 'PROCEDURE DIVISION' to '.'
   count = NF;               # Argument count in line set to fields count
   if (/PROCEDURE DIVISION/) # If 'PROC. DIV.' 
      count -= 2;            #   PROC. and DIV. aren't arguments
   if (/USING/) {            # If 'USING'
      proceed_args=1;        #   set flag 'USING', args coming..
      --count;               #   'USING' is'nt an argument
   }                         #
   if (NF == ".")            # If final point alone (not 
      --count;               #   '.' isn't an argument
   if (proceed_args)         # If flag arguments coming set
       args_count += count;  #   add new arguments found in the line
}

END {                        # All input files have been read
   print_args_count();       # Print argument count for last file
}

Jean-Pierre.

I have modified my awk program to remove from input lines all chars from the first * to the end of line.

but still the this file give as

7.cob #Args=8

7.cob----
I2OCR *PROCEDURE DIVISION USING XXXXXX
PROCEDURE DIVISION
CHANGE FOR ENDS
USING
CHANGE FOR BEGINS
AAAA
BBBBB
CCCC
DDDD
EEEE
FFFF
GGGG
.

Modify the following statement :

   if ($NF == ".")            # If final point alone

Jean-Pierre.

Thanks a lot Jean-Pierre

Its works great.....

Hi

I am using the awk Script developed by Jean-Pierre

I need a small modification in the Script.....

This time i am searching form the Call to the Particular Program with USING + Agruments...

Let me be clear

Input is

       PERFORM AAAA-CALL-PROGRAM.                         
   AAAA-CALL-PROGRAM.                                     
       CALL 'PROGRAM' USING CCCCC
                                  DDDDD.                

In Input i search for CALL 'PROGRAM' and See How many Arguments are Passed to it...
IN this case it 2..

I tried Modifying the Script as follows

/.[ ]*CALL.'\''PROGRAM/,/\./ {
count = NF;
if (/.[ ]*CALL.'\''PROGRAM/) # If CALL PROGRAM
count -= 2; # CALL and PROGRAM aren't arguments
if (/USING/) {
proceed_args=1;
--count;

But this Gives me

temp #Args=0 even if i have two args CCCCC and DDDDD..

Is Suppose some Problem in my Pattern matching.. I used '\'' to search for '(Single Quote)

I wanted to match if the Called Program and the Calling Program use the Same Number of Arguments... for that I was trying this script..