Reputation: 329
I'm new to perl so please excuse me if my question seems obvious. I made a small perl script that just examines itself to extract a particular substring I'm looking for and I'm getting results that I can't explain. Here is the script:
use 5.006;
use strict;
use warnings;
use File::Find;
my @files;
find(
sub { push @files, $File::Find::name unless -d; },
"."
);
my @filteredfiles = grep(/.pl/, @files);
foreach my $fileName (@filteredfiles)
{
open (my $fh, $fileName) or die "Could not open file $fileName";
while (my $row = <$fh>)
{
chomp $row;
if ($row =~ /file/)
{
my ($substring) = $row =~ /file\(([^\)]*)\)/;
print "$substring\n" if $substring;
}
}
close $fh;
}
# file(stuff)
# directory(stuff)
Now, when I run this, I get the following output:
stuff
[^\
Why is it printing the lines out of order? Since the "stuff" line occurs later in the file, shouldn't it print later?
Why is it printing that second line wrong? It should be "\(([^\
". It's missing the first 3 characters.
If I change my regex to the following: /directory\(([^\)]*)\)/
, I get no output. The only difference is the word. It should be finding the second comment. What is going on here?
Upvotes: 0
Views: 95
Reputation: 118128
use 5.006
kind of odd if you are just beginning to learn Perl ... That is an ancient version.
You should not build a potentially huge list of all files in all locations under the current directory and then filter it. Instead, push only the files you want to the list.
Especially with escaped meta characters, regex patterns can be become hard to read very quickly, so use the /x
modifier to insert some whitespace into those patterns.
You do not have to match twice: Just check & capture at the same time.
If open
fails, include the reason in the error message.
Your second question above does not make sense. You seem to expect your pattern to match the literal string file\(([^\)]*)\)/
, but it cannot.
use strict;
use warnings;
use File::Find;
my @files;
find(
sub {
return if -d;
return unless / [.] pl \z/x;
push @files, $File::Find::name;
},
'.',
);
for my $file ( @files ) {
open my $fh, '<', $file
or die "Could not open file $file: $!";
while (my $line = <$fh>) {
if (my ($substring) = ($line =~ m{ (?:file|directory) \( ([^\)]*) \) }x)) {
print "$substring\n";
}
}
close $fh;
}
# file(stuff)
# directory(other)
Output:
stuff
other
Upvotes: 1