Tuna has asked for the wisdom of the Perl Monks concerning the following question:

I am creating a script which when given a date range, will grab certain files created during those dates, in order to determine what differences exist, if any. I was planning on using Array::Compare to make my comparisons.

Here is some code:
#!/usr/local/bin/perl use strict; use Array::Compare; ############################## # Define some variables here # ############################## my ( @pub, @priv, @as, @files, @lines ); my ( $num, $from, $to, $AS, $privstring, $pubstring, $element, $beg_priv_file, $beg_pub_file, $comp_file, $as_dir, $line ); my $dir = "path-to-peering-files"; ################### # test invocation # ################### die "\nUsage: $0 <AS> <yyyymmdd-yyyymmdd>\n This program will take peering files, as per AS specified on the command line where AS = [123, 456, 789, 111, 222] choose multiple AS's by comma-separating them for example, \"123,456,789\" -a to process all valid AS's\n\n" unless @ARGV; unless (($from, $to) = $ARGV[1] =~ /(\d{8})-(\d{8})/) { die "Invalid dates or date format\n"; } unless ($from < $to){ die "Invalid date range\n"; } $AS = $ARGV[0]; my @as = split(",", $AS); foreach $num(@as){ die "AS $num is not recognized. Please choose [123, 456, 789, 111, 222]\n" unless ($num == 123 || $num == 456 || $num == 789 || $num == 111 || $num == 222 || $num == "-a"); } ######################### # Set AS(s) to process # ######################### if ($AS == "-a"){ @as = qw(123 456 789 111 222); } ############################## # Begin file processing here # ############################## foreach $num(@as) { &get_routers($num); } ############### # SUBROUTINES # ############### sub get_routers { #################################### # set file prepend according to AS # #################################### if ($num = "123") { $privstring = "private-peering."; $pubstring = "public-peering."; $as_dir = "$dir/AS$num"; } elsif ($num = "456") { $privstring ="global-public-peering."; $pubstring = "global-private-peering."; $as_dir = "$dir/AS$num"; } elsif ($num = "789") { $privstring = "ebiz-public-peering."; $pubstring = "ebiz-private-peering."; $as_dir = "$dir/AS$num"; } elsif ($num = "111") { $privstring = "euro-public-peering."; $pubstring = "euro-private-peering."; $as_dir = "$dir/AS$num"; } else { $privstring = "asia-public-peering."; $pubstring = "asia-private-peering."; $as_dir = "$dir/AS$num"; } } opendir (DIR, $as_dir) || die "Cannot open $as_dir: $!.\nRestart this program without AS$AS, or go find out what's wrong, and re-run the program.\n"; @files = grep { /(\d{8})/ && $1 >= $from && $1 <= $to } readdir DIR; ############################################### # push private-peering files into an array, # # and public-peering files into another array # ############################################### foreach my $t(@files){ if ($t =~/^$privstring(\d+$)/){ push(@priv, $t); } elsif ($t =~/^$pubstring(\d+$)/){ push(@pub, $t); } } $beg_priv_file = shift(@priv); $beg_pub_file = shift(@pub); open (BEG_PRIV_FILE, "$as_dir/$beg_priv_file") || die "Cannot open: $!\n"; LINE: while (<BEG_PRIV_FILE>){ chomp; if (/unknown/) { next LINE;} elsif (/shutdown/) { next LINE;} @lines = $_; }
This is where I am stuck. I don't know how to open each of the other files in  @priv and  @pub and write them to dynamically created arrays; one for each file. And, as I'm writing this I just realized that in order to be accurate, I will need to:
now this is pseudo-code, so don't bash me here! if $element(@beginning_file) doesn't exist in @next_file Print something to STDOUT that I will define later. AND if $element(@next_file) doesn't exist in @beginning_file Print something else to STDOUT that I will define later
I'm really stuck. Can anyone help me out?

Replies are listed 'Best First'.
Re: Arrays of files from an array of file names
by davorg (Chancellor) on Feb 18, 2001 at 13:33 UTC

    Heh! I recognise some of that code :) _And_ you're planning to use one of my modules to do the array comparison.

    In general, if you have a list of filenames and want to get a list of file contents then you'd better be sure that the files are small or you've got a lot of memory! That being said, you can do it like this:

    my @files = qw(file1 file2 file3); my @contents; foreach (@files} { open FILE, $_ or do { warn "Can't open $_: $!\n"; next } local $/; push @contents, <FILE>; }

    This gives you each file's contents in a scalar. To get an array of each file's contents you'd do this:

    my @files = qw(file1 file2 file3); my @contents; foreach (@files} { open FILE, $_ or do { warn "Can't open $_: $!\n"; next } push @contents, [<FILE>]; }
    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

      Thanks for pointing out a very simple concept that I was overlooking completely. I was thinking that I needed to write each individual file to it's own array, for comparison 1 file at a time. Yeah, why not write all of the "non-beginning" files to one array!!! BTW, yes, the file sizes are very small; usally between 9k - 11k. Thanks for all of your help, as well as providing me (and others) with Array::Compare.


      Steve
      I do NOT want to sound ingrateful.....but, I'm trying your code and failing miserably.:
      #!/usr/bin/perl -w use strict; my $file1 = "trixee"; #just some nicknames! my $file2 = "limo"; my $file3 = "nata"; my @files = qw(file1 file2 file3); my @contents; foreach (@files) { open FILE, $_ or do { warn "Can't open $_: $!\n"; next } push @contents, [<FILE>]; } foreach my $tmp(@contents) { print "$tmp\n"; }
      This fails with:

      "syntax error at ./testsub.pl line 16, near "push"
      "Execution of ./testsub.pl aborted due to compilation errors".

      Any ideas?
        First, are you sure @files isn't supposed to be ($file1, $file2, $file3)? Right now, you're just setting it to the STRINGS ('file1', 'file2', 'file3').

        Anyway, you're missing the semicolon at the end of the do BLOCK expression on line 14. do BLOCK turns a BLOCK (which DOESN'T need a semicolon at the end) into an expression.

        And you can get away from that by doing:
        open FILE, $_ or warn("...: $!"), next;


        japhy -- Perl and Regex Hacker