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

Hello Perl Monks, I am trying to parse multiple files from a directory line by line. There are multiple fields in the log file and I am taking example of one field. Here is my script:
#!/usr/bin/perl chdir("c:/perl/logs") or die "$!"; opendir (DIR, ".") or die "$!"; my @files = grep {/2010*/} readdir DIR; close DIR; { local @ARGV = @files; foreach my $file (@files) { open(FILE,"c:/perl/logs/$file") or die "No file !"; while (@logs = <FILE>) { foreach $odate (@logs) { if ($odate =~/\bdate=(\d{1,4}-\d{1,2}-\d{1,2})/i) { $date = $1; print "$date\n"; ### prints all dates from all files } } print "$date\n"; ### Only prints last date from each f +ile } } } close FILE; exit(0);

I am trying to get all date values from all files in $date and I want to use these values outside the foreach loop. but still inside the while loop.
Please let me know if there is another way to accomplish this, I am new to perl and still learning.

Replies are listed 'Best First'.
Re: Scalar looses values outside foreach loop
by Corion (Patriarch) on Dec 02, 2010 at 09:20 UTC

    If you want to collect all date values, you will need an array, not a scalar:

    my @dates; foreach $odate (@logs) { if ($odate =~ /\bdate=(\d{1,4}-\d{1,2}-\d{1,2})/i) { push @dates, $1; print "Found $1 as a new date\n"; } } print "I collected the following dates: @dates\n"; for my $date (@dates) { print "Processing $date\n"; };

    Also, while the following code works, it could be written differently:

    while (@logs = <FILE>) { foreach (@logs) { ...

    The above code reads the contents of FILE into @logs in one go, and then iterates over that list one by one. You can roll the two "loops" into one by eliminating @logs and using:

    while (my $odate = <FILE>) { ... };
      Thanks for the quick reponse Corion!
      Can I push these array entries in mysql table ?
      I know for scalar it works, Also when I print array it shows output side by side even after provinding \n.

        What do you mean by "Can I push these array entries in mysql table ?" ? Do you want to write the information into a Mysql database table? If so, you need to write them one by one.

        For outputting the array, you can either interpolate it as I showed you, or print it item by item, as I also showed you.

Re: Scalar looses values outside foreach loop
by locked_user sundialsvc4 (Abbot) on Dec 02, 2010 at 13:41 UTC

    I have the very uncomfortable feeling that you have just slap-dashed something together, and now you are asking the community to debug your code for you ... by inspection.

    Yes, the defects in this code can indeed be located by inspection.   But... how are you going to acquire the ability to do the same?   I am quite serious.   You want to be a fisherman.   You need to learn how to fish ... and how to clean the net ... and how to scrap the barnacles off the boat ... and how far you can actually go on a tank of diesel when the tide is against you ... and ...

      You are right,
      But as I said I am still learning pearl, I am not a programmer and I have recently started learning pearl, The code I posted was small and I asked the community to let me know where I went wrong, I was stuck.
      Answers from Corion and Anonymous explain a lot.
      Thanks.
Re: Scalar looses values outside foreach loop
by choroba (Cardinal) on Dec 02, 2010 at 12:50 UTC
    Instead of grep {/2010*/}, you probably meant grep {/2010.*/}. Or do you really want to include files from 2011?
      Actually, more like files from 201.
      >perl -e "my $foo=\"201 AD\"; if ($foo =~ /(201*)/) {print $1 . \"\n\" +;}" 201

      CE or BC is undefined.

      But in either 201 (undef), most files were papyrus or clay tablets. It's really hard to grep thru those.

Re: Scalar looses values outside foreach loop
by Anonymous Monk on Dec 02, 2010 at 14:57 UTC
    #!perl use strict; use warnings; use feature 'say'; # Perl 5.10.0 and later use autodie; # makes chdir and open failures fatal errors use File::DosGlob 'glob'; # changes glob() to use DOS wildcards my $dir = "c:/perl/logs"; my @dates; chdir $dir; for my $filename (grep {-f} glob '2010*') { open my $fh, '<', $filename; while (<$fh>) { if (my ($date) = /\bdate=(\d{1,4}-\d{1,2}-\d{1,2})/i) { push @dates, $date; } } } say for @dates;