An Awk Program to Create an Awk Program [Long] 
Author Message
 An Awk Program to Create an Awk Program [Long]

all --

There have been several problems recently posted which
the following script may help with.

Script mkawkfld.awk is a script I wrote so users at my
company could easily slurp report text into their PeeCee
spread sheet programs.

Here is how it works.  Say we have a report lin a text file
something ike the following:

####################### cut here ###################
------------------------------------------------------------------ Page   1 ---
Report:  My Company Employee Pay Rate Listing                      
Select:  Office = 'OC' .and. PayType = 'S'
Date..:  02/22/98
Uid...:  konrad
-------------------------------------------------------------------------------

Social Sec   LastName          FirstName       M  Off   T  P    PayRate
===========  ================  ==============  =  ====  =  =  =========
999-99-9999  Am                Sam             I  OC    S  B     987.65
888-88-8888  Butthead          Billy           B  OC    S  B     765.43
777-77-7777  Crastinator       Pro                OC    S  B     000.00
666-66-6666  Listing           E               E  OC    S  B     789.00
555-55-4444  Nobody            Irma            M  OC    S  B    1234.56
####################### cut here ###################

I have the user create a .dfn file like this in their word processor
and save it to say, report.dfn:

####################### cut here ###################
#  Index   Field Name      Type    Posn    Length  Comments
#  ======  ==============  ======  ======  ======  ===========================
   0-001   EE_SSN          Char        1      11   # 999-99-9999
   0-002   EE_Last         Char       14      16   #
   0-003   EE_First        Char       32      14   #
   0-004   EE_MI           Char       48       1   #
   0-005   Office          Char       51       4   #
   0-006   PayType         Char       57       1   # Set = {H,S,E,C}
   0-007   PayPeriod       Char       60       1   # Set = {D,W,B,S,M}
   0-008   PayRate         Money      63       9   # 999999.99
#  End
####################### cut here ###################

I run awk script mkawkfld.awk on report.dfn and get an
awk program that knows how to extract fixed-field data
from the report output file.

Note -- no spaces allowed in the field names ( this is
a regular issue at the office )

I usually have to set up a regex to differentiate data
from headers and footers ( for example, each interesting
record in the report has a SSN field ).

Here is the ready to run output from mkawkfld.awk with
a SSNRegEx and a match( ) added ( saved to say, report.awk ):

( If the user will run this more than once, I save it to
  our awk library dir and put a sh wrapper around it )

####################### cut here ###################
BEGIN {

   # I often change Q0 to "" and Q2 to "|" -- this gives a '|' delim'd file

   Q0 = "\""
   Q2 = "\",\""

   F_EE_SSN           =    1 ; Col [  1 ] =    1 ; Len [  1 ] =   11
   F_EE_Last          =    2 ; Col [  2 ] =   14 ; Len [  2 ] =   16
   F_EE_First         =    3 ; Col [  3 ] =   32 ; Len [  3 ] =   14
   F_EE_MI            =    4 ; Col [  4 ] =   48 ; Len [  4 ] =    1
   F_Office           =    5 ; Col [  5 ] =   51 ; Len [  5 ] =    4
   F_PayType          =    6 ; Col [  6 ] =   57 ; Len [  6 ] =    1
   F_PayPeriod        =    7 ; Col [  7 ] =   60 ; Len [  7 ] =    1
   F_PayRate          =    8 ; Col [  8 ] =   63 ; Len [  8 ] =    9

   NumFld =    8
   RecLen =   71

   # I added this regex manually

   SSNRegEx = "[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]"

Quote:
}

function Trim( InStr ) {

   gsub( "^ *", "", InStr )
   gsub( " *$", "", InStr )

   return( InStr )

Quote:
}

{
   # the commented line was generated by mkawkfld.awk.

   # if (( index( $1, "#" ) != 1 ) && ( length( $0 ) >= RecLen ))

   # I changed it to use the SSNRegEx

   if ( match ( $1, SSNRegEx ))
   {
      EE_SSN           = Trim( substr( $0, Col [  1 ], Len [  1 ] ))
      EE_Last          = Trim( substr( $0, Col [  2 ], Len [  2 ] ))
      EE_First         = Trim( substr( $0, Col [  3 ], Len [  3 ] ))
      EE_MI            = Trim( substr( $0, Col [  4 ], Len [  4 ] ))
      Office           = Trim( substr( $0, Col [  5 ], Len [  5 ] ))
      PayType          = Trim( substr( $0, Col [  6 ], Len [  6 ] ))
      PayPeriod        = Trim( substr( $0, Col [  7 ], Len [  7 ] ))
      PayRate          = Trim( substr( $0, Col [  8 ], Len [  8 ] ))

      printf( "%s%s", Q0, EE_SSN )
      printf( "%s%s", Q2, EE_Last )
      printf( "%s%s", Q2, EE_First )
      printf( "%s%s", Q2, EE_MI )
      printf( "%s%s", Q2, Office )
      printf( "%s%s", Q2, PayType )
      printf( "%s%s", Q2, PayPeriod )
      printf( "%s%s", Q2, PayRate )
      printf( "%s\n", Q0 )

   }

Quote:
}

####################### cut here ###################

Here is the output from nawk -f report.awk report.out.
Most spreadsheets can read this without a 'Wizard'.

####################### cut here ###################
"999-99-9999","Am","Sam","I","OC","S","B","987.65"
"888-88-8888","Butthead","Billy","B","OC","S","B","765.43"
"777-77-7777","Crastinator","Pro","","OC","S","B","000.00"
"666-66-6666","Listing","E","E","OC","S","B","789.00"
"555-55-4444","Nobody","Irma","M","OC","S","B","1234.56"
####################### cut here ###################

Finally, here is mkawkfld.awk.  Save this to a handy
directory as mkawkfld.awk and go to town ;-)

####################### cut here ###################
BEGIN {

   F_Name = 2
   F_Type = 3
   F_Col  = 4
   F_Len  = 5

   Starter = "# *[Ii][Nn][Dd][Ee][Xx]"
   Ender   = "# *[Ee][Nn][Dd]"

   while ( getline > 0 )
   {
      if ( match( $0, Starter ) > 0 )
         break
   }

   NumFld = 0
   RecLen = 0

   printf( "#\n# This script was auto generated by program mkawkfld.awk\n#\n" )
   printf( "BEGIN {\n" )
   printf( "\n" )
   printf( "   Q0 = \"\\\"\"\n" )
   printf( "   Q2 = \"\\\",\\\"\"\n" )
   printf( "\n" )

Quote:
}

{
   if (( NF >= F_Len ) && ( index( $1, "#" ) == 0 ))
   {

      Name [ ++NumFld ] = $(F_Name)

      printf( "   F_%-16s = %4d ; Col [ %2d ] = %4d ; Len [ %2d ] = %4d\n", \
               $(F_Name), NumFld, NumFld, $(F_Col), NumFld, $(F_Len) )

      if (( L = $(F_Col) + $(F_Len) - 1 ) > RecLen )
         RecLen = L

   }
   else if ( index( $0, Ender ) > 0 )
      exit

Quote:
}

END {

   if ( NumFld == 0 )
      printf( "}\n" )
   else
   {
      printf( "\n" )
      printf( "   NumFld = %4d\n", NumFld )
      printf( "   RecLen = %4d\n", RecLen )
      printf( "\n" )
      printf( "}\n" )

      printf( "function Trim( InStr ) {\n" )
      printf( "\n" )
      printf( "   gsub( \"^ *\", \"\", InStr )\n" )
      printf( "   gsub( \" *$\", \"\", InStr )\n" )
      printf( "\n" )
      printf( "   return( InStr )\n" )
      printf( "}\n" )

      printf( "{\n" )
      printf( "   if (( index( $1, \"#\" ) != 1 ) && ( length( $0 ) >= RecLen ))\n" )
      printf( "   {\n" )

      for ( i = 1 ; i <= NumFld ; i ++ )
      {
         printf( "      %-16s = Trim( substr( $0, Col [ %2d ], Len [ %2d ] ))\n", \
                        Name [i], i, i )
      }

      printf( "\n" )
      printf( "      printf( \"%%s%%s\", Q0, %s )\n", Name [1] )

      for ( i = 2 ; i <= NumFld ; i ++ )
         printf( "      printf( \"%%s%%s\", Q2, %s )\n", Name [i] )

      printf( "      printf( \"%%s\\n\", Q0 )\n" )
      printf( "\n" )
      printf( "   }\n" )
      printf( "}\n" )
   }

Quote:
}

####################### cut here ###################

There is lotsa room for improvement here but for now, it does
what I need.

HTH

-- kjh
--
------------------------------------------------------------

1111 Seacoast Dr.  Unit 41   |  home:   (619) 423-4451     |
Imperial Beach, CA   91932   |                             |



Thu, 10 Aug 2000 03:00:00 GMT  
 
 [ 1 post ] 

 Relevant Pages 

1. AWK newbie is looking for a AWK help with his 1st program

2. Are longer programs possible in Awk?

3. AWK programs

4. Newbie question -- to make an awk program act on a collection of files

5. Books on AWK programming

6. Making awk programs look pretty

7. Awk Menu Program - Help Needed

8. AWK Menu Program - Help Needed

9. insert \f in awk program

10. Use External commands inside AWK program ?

11. semi-commercial: Effective AWK Programming now available from O'Reilly

12. Checking (compile only) AWK programs

 

 
Powered by phpBB® Forum Software