0

I have an array filled with 4 digit numbers (@nums) that correspond to conf files which use the numbers as the file name, like so: 0000.conf

I am reading a file foreach element in the array and checking the file for a pattern like this :

use strict;
use warnings;

foreach my $num (@nums) {
    open my $fh, "<", "$num.conf"
      or warn "cannot open $num.conf : $!";
    while(<$fh>) {
        if (/^SomePattern=(.+)/) {
            print "$num : $1\n";
        }
    }
}

I am extracting the part of the pattern I want using () and the special var $1.

This seems to be working except it only prints the results of the last file that is opened, instead of printing the results each time the foreach loop passes and opens a file, which is what I expected.

I am still learning Perl, so any detailed explanations of what I missing here will be greatly appreciated.

10
  • There are errors like Global symbol "$num" requires explicit package name at.. How do .conf files look like? Commented Nov 17, 2013 at 16:05
  • you are missing the closing } for the while loop for starters Commented Nov 17, 2013 at 16:06
  • sorry for the typos I have declared "$num" with my and I do have the closing bracket for the while loop both in my original code and I added them here. The .conf files area few hundred lines each. I know that "/^SomePattern=(.+)/" is in each file. Commented Nov 17, 2013 at 16:20
  • 2
    There is nothing wrong with your code, so .conf files should be questioned. Commented Nov 17, 2013 at 16:23
  • 1
    The biggest difference I see between your "example" code and @Davs answer, is Davs specifies how @nums comes to be. Your code does not, and @nums is a magical value that comes from nowhere, and as such, your code is not "complete". Commented Nov 17, 2013 at 17:30

3 Answers 3

1
use v5.16;
use strict;
use warnings;

my @nums = qw/ 0000 0200 /;

for my $num (@nums){
    open my $fh, "<", "$num.conf" or die;
    while (<$fh>) {
        chomp;
        if( /^somePattern=(.+)/ ) {
            say "$1";
        }
    }
    close $fh;
}

this seems to be working for me..You are missing the close $fh; in your code, maybe that is wrong. Secondly, maybe only one of your files matches you regex, check the content for typos. I myself don't use foreach, maybe you are missing 'my' before $num. Depending of your regex, it might be useful to strim newline characters from the end of line with 'chomp'.

Sign up to request clarification or add additional context in comments.

3 Comments

Perl will automatically close the old file when a new file handle is assigned to $fh. Good point about the regex. for is just 'short' for foreach (Perl parses the former as the latter). Use chomp not chop to remove the input record character (usually \n), but that wouldn't matter here since (.+) wouldn't match \n in the OP's regex.
yeah, chomp should be used, not chop, that was a typo.
I rewrote my code like your example, and it is working now... Still not sure of the exact problem with my code though.
1

Your code is excellent for a learner.

The problem is that, using "$num.conf", you are trying to open files named 0.conf etc. instead of 0000.conf.

You should also use the value of $! in your die string so that you know why the open failed.

Write this instead

my $file = sprintf '%04d.conf', $num;
open my $fh, '<', $file or die "Unable to open '$file': $!";

Comments

0

I have left my previous answer as it may be useful to someone. But I missed your opening "I have an array filled with 4 digit numbers".

Doubtless you are populating your array wrongly.

If you are reading from a file then most usually you have forgotten to chomp the newline from the end of the lines you have read.

You may also have non-printable characters (usually tabs or spaces) in each number.

You should use Data::Dumper or the better and more recent Data::Dump to reveal the contents of your array.

2 Comments

my @nums array looks something like this : $VAR = [ '0000', '0001', ];
Are you populating it in the program like that? There is no difference between my @nums = ('0000', '0001') and my @nums = qw/ 0000 0001 / except that the latter is designed to be easier to type. If you don't show the assignment to @nums then we can't really help you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.