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

Hey, so im trying to write this script that will go through the current directory open up file types grab all "SRS_####" and sort them. now that part works but im also trying to grab the equivalent .log file that is associated with the ctl. basically every #_##_XXXXXXXX.CTL will have a .log that goes with it. i wanna add the SRS_#### that is referenced within the log and add it to the current hash table.
sub main(){ my @files = glob("*.{ctl,inc}"); my %srss; open (OUT, ">SRS_List.txt") or die "Can't open file: SRS_List.txt" +; foreach my $file (@files){ open (IN, $file) or die "Can't open file: $file"; while (<IN>){ if (my @matches = ($_ =~ /SRS[_\s]?(\d+)/gi)){ foreach my $match (@matches){ if (!$srss{$match}){ $srss{$match} = 1; } } } } close (IN); print (OUT $file."\n"); if (keys %srss){ print OUT "SRS_(".join("|", sort {$a <=> $b}(keys %srss)). +")"; %srss = undef; } else{ print(OUT "NONE"); } print (OUT "\n\n"); } close(OUT); } main();

Replies are listed 'Best First'.
Re: adding another file type to a hash table
by Anonymous Monk on Dec 17, 2014 at 20:44 UTC

    I don't see any code that opens a log file, perhaps you could show us your attempt so far and tell us what problems you had with it. Other than that, we'd at least need to see some short but representative sample input to give further recommendations - see How do I post a question effectively?

    File::Basename might be helpful in figuring out the filename of the log file:

    use File::Basename 'fileparse'; my $file = "1_23_XXXXXXXX.CTL"; my ($name,$path,$suffix) = fileparse($file,qr/\.ctl$/i); my $logfile = "$path$name.log"; print "$logfile\n"; # "./1_23_XXXXXXXX.log"
      Im new to perl i got tasked with adding that feature to this, this code you see here looks for file types .CTL,.INC and extracts the reg exp SRS_#### and puts it into a table SRS_(####|####)$ what i want to do and have no idea how to go about it is also look for the .CTLs LOG file that gets created it will have the same name as the .CTL just have .LOG instead, i wanna extract the SRS_#### from the .LOG file also, and add it to the current table being created. this is what i added so far but i know its not going to do anything.
      sub main(){ my @files = glob("*.{ctl,inc}"); my %srss; open (OUT, ">SRS_List.txt") or die "Can't open file: SRS_List.txt" +; foreach my $file (@files){ open (IN, $file) or die "Can't open file: $file"; while (<IN>){ if (my @matches = ($_ =~ /SRS[_\s]?(\d+)/gi)){ foreach my $match (@matches){ if (!$srss{$match}){ $srss{$match} = 1; } } } } if / \.log$/ while (<IN>){ if (my @matches = ($_ =~ /SRS[_\s]?(\d+)/gi)){ foreach my $match (@matches){ if (!$srss{$match}){ $srss{$match} = 1; } } } } close (IN); print (OUT $file."\n"); if (keys %srss){ print OUT "SRS_(".join("|", sort {$a <=> $b}(keys %srss)). +")"; %srss = undef; } else{ print(OUT "NONE"); } print (OUT "\n\n"); } close(OUT); } main();

        Hi GotSilk

        It is not clear to me what you are asking for. From the code it looks like you are collecting all the digits from any character stream beginning with /SRS[_\s\]?/ out of some files ending in .ctl or .log

        # Create some files $touch {1..3}{a..c}.{ctl,log} $ls 1a.ctl 1a.log 1b.ctl 1b.log 1c.ctl 1c.log 2a.ctl 2a.log 2b.ctl + 2b.log 2c.ctl 2c.log 3a.ctl 3a.log 3b.ctl 3b.log 3c.ctl 3c. +log junk.pl $echo "SRS_222" >> 1c.ctl $echo "SRS_333" >> 1c.log $echo 'SRS_111SRS_2222SRS_3333' > 1a.log
        #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; opendir(my $dh, '.') or die $!; my @files = map { /(.*)\.ctl$/ }readdir $dh; my %srss; for (@files) { # $_ is set to each element in @files for my $extension(qw(ctl log)) { my $file = "$_.$extension"; open (my $fh, $file) or die $!; while (my $line = <$fh>) { while ($line =~ /SRS[_\s]?(\d+)/g) { $srss{$1} = 1; } } } } print join '|', sort {$a <=> $b} keys %srss; # 111|222|333|2222|3333
        But maybe later you want to store more information such as what file the line was found in. A more complex data structure is needed.
        #!/usr/bin/env perl use strict; use warnings; use Data::Dump; opendir(my $dh, '.') or die $!; my @files = map { /(.*)\.ctl$/ }readdir $dh; my %hashSlice; @hashSlice{@files} = undef; my $srss; $srss->{files} = { %hashSlice } ; for (@files) { # $_ is set to each element in @files for my $extension(qw(ctl log)) { my $file = "$_.$extension"; open (my $fh, $file) or die $!; while (my $line = <$fh>) { while($line =~ /SRS[_\s]?(\d+)/g) { $srss->{files}{$_}{$extension}{$1} = ' +Found'; } } } } dd $srss; { files => { "1a" => { log => { 111 => 1, 2222 => 1, 3333 => 1 } }, "1b" => undef, "1c" => { ctl => { 222 => 1 }, log => { 333 => 1 } }, "2a" => undef, "2b" => undef, "2c" => undef, "3a" => undef, "3b" => undef, "3c" => undef, }, }
        While more complicated this has the advantage of showing which files did not have matches, which ones did, and what file extension they were found in. You can see all of the perl documentation with the perldoc commands. 'perldoc perl' will give you tons of material to read on the command line. There is a ton of references out there to learn from. There is a really concise tutorial at Learn Perl in 2.5 hours. Hope this helps.