I have an array that contains the data from a text file.
I want to filter the array and copy some information to another array. grep
seems to not work.
Here's what I have
$file = 'files.txt';
open (FH, "< $file") or die "Can't open $file for read: $!";
@lines = <FH>;
close FH or die "Cannot close $file: $!";
chomp(@lines);
foreach $y (@lines){
if ( $y =~ /(?:[^\\]*\\|^)[^\\]*$/g ) {
print $1, pos $y, "\n";
}
}
files.txt
public_html
Trainings and Events
General Office\Resources
General Office\Travel
General Office\Office Opperations\Contacts
General Office\Office Opperations\Coordinator Operations
public_html\Accordion\dependencies\.svn\tmp\prop-base
public_html\Accordion\dependencies\.svn\tmp\props
public_html\Accordion\dependencies\.svn\tmp\text-base
The regular expression should take the last one or two folders and put them into their own array for printing.
A regex can get very picky for this. It is far easier to split the path into components and then count off as many as you need. And there is a tool that fits your exact purpose, the core module File::Spec
, as mentioned by xxfelixxx in a comment.
You can use its splitdir
to break up the path, and catdir
to compose one.
use warnings 'all';
use strict;
use feature 'say';
use File::Spec::Functions qw(splitdir catdir);
my $file = 'files.txt';
open my $fh, '<', $file or die "Can't open $file: $!";
my @dirs;
while (<$fh>) {
next if /^\s*$/; # skip empty lines
chomp;
my @all_dir = splitdir $_;
push @dirs, (@all_dir >= 2 ? catdir @all_dir[-2,-1] : @all_dir);
}
close $fh;
say for @dirs;
I use the module's functional interface while for heavier work you want its object oriented one. Reading the whole file into an array has its uses but in general process line by line. The list manipulations can be done more elegantly but I went for simplicity.
I'd like to add a few general comments
Always start your programs with use strict
and use warnings
Use lexical filehandles, my $fh
instead of FH
Being aware of (at least) a dozen-or-two of most used modules is really helpful. For example, in the above code we never had to even mention the separator \
.
I can't write a full answer because I'm using my phone. In any case zdim has mostly answered you. But my solution would look like this
use strict;
use warnings 'all';
use feature 'say';
use File::Spec::Functions qw/ splitdir catdir /;
my $file = 'files.txt';
open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
my @results;
while ( <$fh> ) {
next unless /\S/;
chomp;
my @path = splitdir($_);
shift @path while @path > 2;
push @results, catdir @path;
}
print "$_\n" for @results;