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

I am writing a simple script and need a quick bit of help with a regex. I have text that equals this:
\one\two\three\four
I want to return everything AFTER the last back slash. In this case, the text "four"

Can someone help me with a quick regex for this? Thank you.

Replies are listed 'Best First'.
Re: Quick Regex Needed
by Your Mother (Archbishop) on Oct 21, 2008 at 19:01 UTC

    I don't know how fast this is compared to possible regular expressions but this is how I'd start -- given the limited problem description -- and benchmark against other options if this (or a variant of it) isn't fast enough.

    my $input = '\one\two\three\four'; my $last = ( split /\\/, $input )[-1]; print $last, "\n";
Re: Quick Regex Needed
by ikegami (Patriarch) on Oct 21, 2008 at 19:28 UTC
      Right, but it's important to know what sort of system you happen to be using, so that you invoke the fileparse_set_fstype() function when necessary:
      $ uname -s Darwin $ echo '\one\two\three\four' \one\two\three\four $ echo '\one\two\three\four' | perl -MFile::Basename -lne 'print basename($_)' \one\two\three\four $ echo '\one\two\three\four' | perl -MFile::Basename -lne 'BEGIN{fileparse_set_fstype("DOS")} prin +t basename($_)' four
      The above would work out the same way if the result of "uname -s" had been linux or unix.

        Only if you assume he wasn't dealing with a path in the first place.

        I assumed the OP was dealing with paths. If he's not, I believe he's better off not using File::Basename at all rather than your workaround.

      With Path::Class, that can be written as
      #!/usr/bin/perl -- use strict; use warnings; use Path::Class; print file(qw' \one\two\three\four ')->basename; print "\n"; __END__ four
Re: Quick Regex Needed
by gwadej (Chaplain) on Oct 21, 2008 at 19:16 UTC
    I would probably use: m/([^\\]+)$/ Since this is a pretty easy regex problem, you obviously need to sit down with a good regex doc and go over the basics. Some useful points:
    1. You are matching at the end of the string so $ is very useful.
    2. You are trying to extract something that does not match a particular character, use a negated character class.
    3. You are trying to extract data, use capturing parentheses.
    Your Mother also gave a good solution, following the advice from Mastering Regular Expressions. "If you know what you want to keep use the match operator, if you know what you want to discard, use split" (paraphrased, badly).
    G. Wade
Re: Quick Regex Needed
by dorko (Prior) on Oct 21, 2008 at 19:01 UTC
    This seems to work: .+\\(.+)

    But it makes some assumptions about your data. Namely there is at least one blackslash and there is at least one character before and after the backslash.

    Cheers,

    Brent

    -- Yeah, I'm a Delt.
Re: Quick Regex Needed
by gone2015 (Deacon) on Oct 21, 2008 at 23:30 UTC

    rindex will find the last '\' for you. As in:

    my $foo = "\\one\\two\\three\\four" ; my $bar = substr($foo, rindex($foo, "\\") +1) ;
    or did it have to be a regex ?

Re: Quick Regex Needed
by DutchCoder (Scribe) on Oct 21, 2008 at 18:53 UTC

    Why wouldn't a regular expression be fast enough? How quick must it be?

    With a little light reading and trial-and-error you might come up with something like this:

    my $quick = '\one\two\three\four'; my $endpart = ($quick =~ m/([^\\]*)$/ ) ? $1 : ''; print qq|The end part is $endpart\n|;

      Silent updates are kind of bad form. :( Your post was one line last I saw it.

        Yeah, I know, but I couldn't resist putting in a silly remark while working on something helpful (the question just screamed for it). But all is well now :D
Re: Quick Regex Needed
by Anonymous Monk on Oct 22, 2008 at 01:32 UTC
    #!/usr/bin/perl -- use strict; use warnings; my $str = qw~ \one\two\three\four ~; print "$str\n"; print "$1\n" if $str =~ m~[\\/]([^\\/]+)$~; print $str =~ m~[\\/]([^\\/]+)$~; print "\n"; print scalar reverse($1),"\n" if reverse($str) =~ m~^([^\\/]+)~; print scalar reverse( reverse($str) =~ m~^([^\\/]+)~); # sexeger print "\n"; use YAPE::Regex::Explain; print YAPE::Regex::Explain->new(qr~[\\/]([^\\/]+)$~)->explain; __END__ \one\two\three\four four four four four The regular expression: (?-imsx:[\\/]([^\\/]+)$) matches as follows: NODE EXPLANATION ---------------------------------------------------------------------- (?-imsx: group, but do not capture (case-sensitive) (with ^ and $ matching normally) (with . not matching \n) (matching whitespace and # normally): ---------------------------------------------------------------------- [\\/] any character of: '\\', '/' ---------------------------------------------------------------------- ( group and capture to \1: ---------------------------------------------------------------------- [^\\/]+ any character except: '\\', '/' (1 or more times (matching the most amount possible)) ---------------------------------------------------------------------- ) end of \1 ---------------------------------------------------------------------- $ before an optional \n, and the end of the string ---------------------------------------------------------------------- ) end of grouping ----------------------------------------------------------------------
    sexeger, YAPE::Regex::Explain