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

I have a text file that looks like:

/path/to/one/library /path/to/another /path/to/another/01 /path/to/another/s /path/to/another/02 /path/to/another/w1 /path/to/another/03 /path/to/another/1e /path/to/another/2014

I need to get the LAST directory(whose last name is numeric) 01;02;03;2014

($b) = $line =~ m#([^/]+)$#; ($c) = $line =~ m#(\d+)$#; if ($b eq $c){print "Match \n";}

Replies are listed 'Best First'.
Re: Best way to do this
by choroba (Cardinal) on Sep 29, 2014 at 07:56 UTC
    I'd probably use split to break paths to directories, and check the last one is numeric:
    #!/usr/bin/perl use warnings; use strict; while (my $line = <>) { my $last = ( split m{/}, $line )[-1]; print "$last" if $last =~ /^[0-9]+$/; }
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Thank you
Re: Best way to do this
by davido (Cardinal) on Sep 29, 2014 at 08:19 UTC

    One classic way is to just keep track of the most recent contender, and the one you're still holding at the end is the winner:

    use File::Basename; my $found; while( <DATA> ) { chomp; my $bn = basename($_); next unless $bn =~ m/^\d+$/; $found = $bn; } print $found; __DATA__ /path/to/one/library /path/to/another /path/to/another/01 /path/to/another/s /path/to/another/02 /path/to/another/w1 /path/to/another/03 /path/to/another/1e /path/to/another/2014

    If the file is large enough that you don't want to spend time reading the whole thing, you could use a File::ReadBackwards solution:

    # Untested... use File::Basename; use File::ReadBackwards; tie *FH, 'ReadBackwards', 'filename' or die $!; my $found; while( <FH> ) { chomp; next unless basename($_) =~ m/^(\d+)$/; $found = $1; last; } die "No matches found.\n" unless defined $found; print $found;

    Or if the file's not huge, you could just slurp it into an array and reverse the array:

    use File::Basename; my @files = reverse <DATA>; my $found; foreach ( @files ) { chomp; next unless basename($_) =~ m/^(\d+)$/; $found = $1; last; } die "No matches found.\n" unless defined $found; print $found; __DATA__ /path/to/one/library /path/to/another /path/to/another/01 /path/to/another/s /path/to/another/02 /path/to/another/w1 /path/to/another/03 /path/to/another/1e /path/to/another/2014

    Of course if you're going to slurp it, you probably don't really need the @files variable:

    foreach ( reverse <DATA> ) { ...

    This still slurps, and people generally advise against iterating over a filehandle within a foreach loop, because the foreach loop does implicitly slurp the file. But in this case, that's the behavior we actually want.


    Dave