[comp.lang.perl] Learning perl -- generlized file loading w/var assignment

jas@ISI.EDU (Jeff Sullivan) (02/16/91)

I'm just learning perl, and in doing so, am trying to put together the
beginnings of a project that will be a kind of parser/server.

To that end, I have created a set of files which each contain a list
of commands or terms which I want the user to be able to abbreviate.
I then want to be able to read in this list of files and assign each
file its own associative array filled out by abbrev.pl.  However, my
test doesn't seem to work.

Here's a sample of the code:

#!/usr/bin/perl

# Load abbreviation package
require "abbrev.pl";

#Set abbreviation eval line (run for each abbr file.).
#$filestub will be set to the root of the file name, which is always
#of the form <file-contents>-LIST.
$eval_line = "%$filestub = ();\n&abbrev(*$filestub, @tmp);\n";

#Alternative method to set eval_line.
#$eval_line = <<'End_of_Eval_Line';
#%$filestub = ();
#&abbrev(*$filestub, @tmp);
#End_of_Eval_Line


#Load abbreviation files.

foreach $filename ("ATTR-LIST", "HELP-LIST", "TYPE-LIST", "CMD-LIST") {

    # Open the file for input
    open(TMP, "$filename") || die "Can't load $filename: $!";

    $filename =~ /(\w+)-LIST/;
    $filestub = $1;

    #Slurp in the whole file, one line per element of @tmp
    @tmp = <TMP>;

    # close the file
    close TMP;

    #Initialize the associative array.
    %abbr = ();

    #Fill in the array of abbreviations.
    eval $eval_line;
}

while (<>) {
    chop;
    $long = $cmd{$_};
    print "$long\n" if length($long);
}


The last bit is pulled vrom the example using abbrev.pl.  The $cmd{}
array (should) be created by the eval_line when $filename is
"CMD-LIST" and $filestub is "CMD".  Right?

jas

--
--------------------------------------------------------------------------
Jeffrey A. Sullivan		| Senior Systems Programmer
jas@venera.isi.edu		| Information Sciences Institute
jas@isi.edu                    	| University of Southern California

merlyn@iwarp.intel.com (Randal L. Schwartz) (02/16/91)

In article <16785@venera.isi.edu>, jas@ISI (Jeff Sullivan) writes:
| #Set abbreviation eval line (run for each abbr file.).
| #$filestub will be set to the root of the file name, which is always
| #of the form <file-contents>-LIST.
| $eval_line = "%$filestub = ();\n&abbrev(*$filestub, @tmp);\n";

This stuff is getting double-quote interpreted even before $filestub
is defined.  Blech.

Try this instead:

### if you cut here, you will likely damage your crt. :-) ###
#!/usr/bin/perl

# Load abbreviation package
require "abbrev.pl";

#Load abbreviation files.

foreach $filename ("ATTR-LIST", "HELP-LIST", "TYPE-LIST", "CMD-LIST") {

    # Open the file for input
    open(TMP, "$filename") || die "Can't load $filename: $!";

    $filename =~ /(\w+)-LIST/;
    $filestub = $1;

    # or ($filestub = $filename) =~ s/\W.*//;

    #Slurp in the whole file, one line per element of @tmp
    @tmp = <TMP>;

    chop(@tmp); # toss those newlines

    # close the file
    close TMP;

    #Fill in the array of abbreviations.
    eval <<"END_EVAL"; die $@ if $@;
	%$filestub = ();
	&abbrev(*$filestub, \@tmp);
END_EVAL

}

while (<>) {
    chop;
    $long = $CMD{$_};
    print "$long\n" if length($long);
}
### but if you cut up above, you might as well cut here too. :-) ###

print "Just another Perl hacker,"
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/

composer@chem.bu.edu (Jeff Kellem) (02/16/91)

In article <16785@venera.isi.edu> jas@ISI.EDU (Jeff Sullivan) writes:

 > To that end, I have created a set of files which each contain a list
 > of commands or terms which I want the user to be able to abbreviate.
 > I then want to be able to read in this list of files and assign each
 > file its own associative array filled out by abbrev.pl.  However, my
 > test doesn't seem to work.
 >
 > Here's a sample of the code:
[ ..deleted.. ]
 > #Set abbreviation eval line (run for each abbr file.).
 > #$filestub will be set to the root of the file name, which is always
 > #of the form <file-contents>-LIST.
 > $eval_line = "%$filestub = ();\n&abbrev(*$filestub, @tmp);\n";

First off, there are a few problems with the above $eval_line.  Since you've
enlosed the RHS of the $eval_line assignment in double quotes, the $filestub,
and @tmp will be evaluated immediately.  Since you haven't assigned anything
to $filestub yet (and you want to use the name @tmp as an arg) they get
replaced by their current contents, which happen to be nothing at this point.

When creating code on the fly, it's always a good idea to add:

	print $eval if $debug;

before the actual eval.  Anyways, you probably want to move the
$eval_line assignment into the "foreach $filename" loop after the
$filestub assigment.  Also, you don't need the newlines in this case.
So, with double quotes, the above should be written as:

	$eval_line = "%$filestub = (); &abbrev(*$filestub, \@tmp);";

You want the "@tmp" to stay, as is, so you need to escape the @-sign.

 > #Load abbreviation files.
 >
 > foreach $filename ("ATTR-LIST", "HELP-LIST", "TYPE-LIST", "CMD-LIST") {
 >
[ ..deleted.. ]
 >     $filename =~ /(\w+)-LIST/;
 >     $filestub = $1;
[ ..deleted.. ]
 > while (<>) {
 >     chop;
 >     $long = $cmd{$_};
 >     print "$long\n" if length($long);
 > }
 >
 > The last bit is pulled vrom the example using abbrev.pl.  The $cmd{}
 > array (should) be created by the eval_line when $filename is
 > "CMD-LIST" and $filestub is "CMD".  Right?

Except that variable names are case-sensitive.  So, assuming the code
worked, you would be producing an associative array named %CMD, instead
of %cmd.  If you want to lowercase the part of $filename you're trying
to grab, there are a bunch of ways to do it.  Here's one:

($filestub = $filename) =~ s/^(\w+)-list/(($lc = $1) =~ tr|A-Z|a-z|),$lc/ie;

Okay, maybe you want something a little easier to read for the
beginner.. ;-}  Following your start:

	$filename =~ /(\w+)-LIST/i;
	($filestub = $1) =~ tr/A-Z/a-z/;

You may want the i on the end of the match, //i, so you can match
CMD-LIST and CMD-list and so on... in otherwords, the match ignores
case.

Hope that helps a little...Enjoy Perl!

			-jeff

Jeff Kellem
Internet: composer@chem.bu.edu