[comp.unix.questions] Setting awk variables via a program

brad@SSD.CSD.HARRIS.COM (Brad Appleton) (02/20/91)

I have a program (much more sophisticated than getopt) that will parse
command line arguments for sh, ksh, csh, tcsh, and bash. I would like to
be able to use it for awk as well. When I use it for the bourne-shell,
it looks something like:
----------------------------------------------------------------------------
#!/bin/sh
#	test.sh - Bourne shell script to test out the parseargs command!
#
#  usage: test.sh [-d directory] [-f file [file ...]] [-x] [-y]
#                 name [arguments ...]
#
NAME="`basename $0`";

ARGUMENTS="
  '?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit',
  'd', ARGOPT,    argStr,   dirname, 'DIRectory : working directory',
  'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode',
  'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode',
  'f', ARGLIST,   argStr,   files,   'files : files to process',
  ' ', ARGREQ,    argStr,   name,    'name : name to use',
  ' ', ARGLIST,   argStr,   -- ,     'argv : any remaining arguments',
  ENDOFARGS
"
export ARGUMENTS

yflag='TRUE'     ## set defaults (dir=".")

   ## parse command-line and save assignments in a temporary file ##
parseargs -s sh -e ARGUMENTS -u -- "$NAME" "$@" >/tmp/tmp$$
if [ $? -ne 0 ]
  then rm -f /tmp/tmp$$; exit 2  ## non-zero status (usage given)
fi

   ## evaluate results from parseargs and remove temporary file
. /tmp/tmp$$;  rm -f /tmp/tmp$$

   ## echo  the parsed arguments (use defaults if not defined)
echo "ARGUMENTS:"
echo "=========="
echo "Name='$name', Count='${count:-1}'"
echo "XFlag='$xflag', YFlag='$yflag'"
echo "Directory='${dirname:-"."}'"
echo "Files='$files'"
echo "New Positional Parameters='$*'"
----------------------------------------------------------------------------

Now I would like to do a similar thing for awk-scripts. For the shell(s),
parseargs outputs variable settings which must then be evaluated using
`.' (or `source' or possibly `eval').  Should it do the same type of thing
for awk? Can awk do that?

If not, it should probably return some string that can be massaged (with 
as little effort as possible) to get the desired variables (and/or arrays)
with the values intended on the command-line.

Ive found little in "The AWK Programming Language" to help me in this
endeavor. I was hoping one of you awk-guru's might be able to show me how
its done.

Oh yeah - since PERL is the next logical target, Id appreciate comments on
how to do this for PERL as well!

And before you go off saying awk/perl are sophisticated enough to do this by
themselves without too much trouble, let me just add that my program is rather
sophisticated as well and does a bit more than just parse the command-line in
the usual fashion.

Any help is greatly appreciated!

______________________ "And miles to go before I sleep." ______________________
 Brad Appleton           brad@ssd.csd.harris.com       Harris Computer Systems
                             uunet!hcx1!brad           Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/20/91)

In article <2391@travis.csd.harris.com> brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes:
: I have a program (much more sophisticated than getopt) that will parse
: command line arguments for sh, ksh, csh, tcsh, and bash.

: Now I would like to do a similar thing for awk-scripts. For the shell(s),
: parseargs outputs variable settings which must then be evaluated using
: `.' (or `source' or possibly `eval').  Should it do the same type of thing
: for awk? Can awk do that?

Not very easily.  awk doesn't have eval.  Your best bet would be to have
your first awk script write a second awk script that does the actual work.

: Oh yeah - since PERL is the next logical target, Id appreciate comments on
: how to do this for PERL as well!
: 
: And before you go off saying awk/perl are sophisticated enough to do this by
: themselves without too much trouble, let me just add that my program is rather
: sophisticated as well and does a bit more than just parse the command-line in
: the usual fashion.

Perl is sophisticated enough to do this by itself without too much trouble.

However, if you're very attached to your parseargs program, a wooden
translation of your sh script would look like this:

#!/usr/bin/perl
#	test.pl - Perl script to test out the parseargs command!
#
#  usage: test.pl [-d directory] [-f file [file ...]] [-x] [-y]
#                 name [arguments ...]
#
($NAME = $0) =~ s#.*/##;

$ENV{'ARGUMENTS'}="
  '?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit',
  'd', ARGOPT,    argStr,   dirname, 'DIRectory : working directory',
  'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode',
  'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode',
  'f', ARGLIST,   argStr,   files,   'files : files to process',
  ' ', ARGREQ,    argStr,   name,    'name : name to use',
  ' ', ARGLIST,   argStr,   -- ,     'argv : any remaining arguments',
  ENDOFARGS
";

$yflag='TRUE';     ## set defaults ($dir=".")

   ## parse command-line and save assignments in a temporary file ##
open(PIPE, "-|") ||
    exec 'parseargs', '-s', 'sh', '-e', 'ARGUMENTS', '-u', '--', $NAME, @ARGV;

    ## evaluate results from parseargs, translating foo= and set to Perlese
while (<PIPE>) {
    $_ .= <PIPE> while s/\\\n$//;
    &eval if s/^(\w+=)/\$$1/;
    &eval if s/^set (.*)/\@ARGV = split(' ',<<'EndOfArgs');\n$1\nEndOfArgs/;
    $stuff .= $_;
}
&eval;

sub eval { eval $stuff; $stuff = ''; }

close PIPE;
exit 2 if $?;  ## non-zero status (usage given)

   ## echo  the parsed arguments (use defaults if not defined)

$count = -1 unless defined $count;
$dirname = '.' unless defined $dirname;

print <<"EndOfText";
ARGUMENTS:
==========
Name='$name', Count='$count'
XFlag='$xflag', YFlag='$yflag'
Directory='$dirname'
Files='$files'
New Positional Parameters='@ARGV'
EndOfText
----------------------------------------------------------------------------

Or something like that.  I can't test it without your program, since I don't
know what the output of parseargs looks like.  In particular, I haven't
tried to handle any quoting on the set command that parseargs apparently
produces.

I'd still be inclined to write parseargs as a Perl subroutine.  Of course,
I'm a wee bit biased...

Larry Wall
lwall@jpl-devvax.jpl.nasa.gov