Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Regular Expression Help

by Anonymous Monk
on Nov 18, 2005 at 19:50 UTC ( #509925=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Let's say you have a directory:

/rootdir/sub1/sub2/sub3/sub4/

How would I strip off JUST the last subdir, sub4? Of course, the dir could be called anything, like "/rootdir/sub funky ---doodash/la la la/Proposal for Buttering My Feet" and I would still want to strip off "Proposal for Buttering My Feet", and be 5 or more times long.
Any idea? I figure it's a reg ex like "Look for the last / that isn't the last character and take away everything to the right of it, including itself"
Thanks very much!!!!

Comment on Regular Expression Help
Re: Regular Expression Help
by ptum (Priest) on Nov 18, 2005 at 19:57 UTC
    /.*\/(.*?)$/ will do the trick, I think. Regular expression greed will consume everything up until the last '/' with the first .* and leave only the last subdir.
      It doesn't work.
        Fletch is right -- use File::Basename -- but in the more general case of finding the last token in a string, that regex ought to work:
        #!/usr/local/bin/perl use strict; my $string = '/one/two and three/and four / and five'; if ($string =~ /.*\/(.*?)$/) { print "Last token: $1\n"; }
        Or you could always split on your token separator and grab the last element in the resulting array.
Re: Regular Expression Help
by Fletch (Chancellor) on Nov 18, 2005 at 19:58 UTC
Re: Regular Expression Help
by pg (Canon) on Nov 18, 2005 at 20:16 UTC

    Or utilize rindex: (this code works regarless whether there is a trailing /)

    use strict; use warnings; { my $str = "/rootdir/sub1/sub2/sub3/sub4/"; print substr($str, 0, rindex($str, "/", length($str) - 2)); } print "\n"; { my $str = "/rootdir/sub1/sub2/sub3/sub4"; print substr($str, 0, rindex($str, "/", length($str) - 2)); }

    which prints:

    /rootdir/sub1/sub2/sub3 /rootdir/sub1/sub2/sub3
Re: Regular Expression Help
by ikegami (Pope) on Nov 18, 2005 at 20:18 UTC
Re: Regular Expression Help
by ikegami (Pope) on Nov 18, 2005 at 20:45 UTC

    Both are the following portable and reliable. There difference is what happens when the trailing slash is ommited.

    1) Anything after the last slash is considered a dir name:

    my ($vol, $dirs) = File::Spec->splitpath($path, 1); $dirs = File::Spec->canonpath($dirs); my @dirs = File::Spec->splitdir($dirs); pop(@dirs); $dirs = File::Spec->catdir(@dirs); $path = File::Spec->catpath($vol, $dirs, '');

    Test:

    outputs:

    /rootdir/sub1/sub2/sub3/sub4/ -> \rootdir\sub1\sub2\sub3 /rootdir/sub1/sub2/sub3/sub4 -> \rootdir\sub1\sub2\sub3 /rootdir/ -> \ /rootdir -> \ / -> \ C:\ -> C:\ reldir/sub1/ -> reldir reldir/sub1 -> reldir reldir/ -> reldir ->

    2) Anything after the last slash is considered a file name:

    my ($vol, $dirs) = File::Spec->splitpath($path, 0); $dirs = File::Spec->canonpath($dirs); my @dirs = File::Spec->splitdir($dirs); pop(@dirs); $dirs = File::Spec->catdir(@dirs); $path = File::Spec->catpath($vol, $dirs, '');

    Test:

    outputs:

    /rootdir/sub1/sub2/sub3/sub4/ -> \rootdir\sub1\sub2\sub3 /rootdir/sub1/sub2/sub3/file -> \rootdir\sub1\sub2 /rootdir/ -> \ /rootfile -> \ / -> \ C:\ -> C:\ reldir/sub1/ -> reldir reldir/file -> reldir/ -> relfile ->

    Note: The only difference is the second argument to splitpath.

Re: Regular Expression Help
by TedPride (Priest) on Nov 18, 2005 at 23:38 UTC
    All of the regexes listed above seem to have problems in one or more situations.
    use strict; use warnings; while (<DATA>) { chomp; my ($last) = m|/([^/]+)/[^/]*$|; print "$last\n"; } __DATA__ /rootdir/sub1/sub2/sub3/sub4/ /rootdir/sub1/sub2/sub3/sub4/file /rootdir/ /
Re: Regular Expression Help
by Anonymous Monk on Nov 19, 2005 at 00:30 UTC
    Interesting, I think 'split' when I see something separated by slashes. Off the top of my head, the below code will do what you are looking for:
    my @dirs = qw ( /usr/local/bin/ /var/tmp/somefile / /home/foo/bar ); foreach ( @dirs ) { my @dir; my $lastdir; if ( /^\/$/ ) { $lastdir = "/"; print "$lastdir\n"; next; } if ( /\/$/ ) { chop; } @dir = split('/'); $lastdir = pop(@dir); print "$lastdir\n"; }
    Will print:

    bin
    somefile
    /
    bar

    Sorry if this is hacky code. I'm a Monks newb and have made my career by pounding out this type of randomness.
Re: Regular Expression Help
by ercparker (Hermit) on Nov 19, 2005 at 04:51 UTC
    This strips off the last directory if more than one directory in path:
    foreach my $path (<DATA>) { chomp($path); $path =~ s{(?<=[^/])/[^/]+/?$}{}xms; print $path . "\n"; } __DATA__ /rootdir/sub funky ---doodash/la la la/Proposal for Buttering My Feet /rootdir/sub1/sub2/sub3/sub4/ /rootdir/sub1/sub2/sub3/sub4/file/ /rootdir/ /
    Hope this helps

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://509925]
Approved by friedo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2015-07-05 06:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (60 votes), past polls