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

Can anybody explain how this regex works? $lib_name =~ s/.*\/(.*).lib/$1/;

Replies are listed 'Best First'.
Re: Regex explanation
by Discipulus (Canon) on Sep 14, 2015 at 08:37 UTC
    the regex match anything anytime ('.*') then a unix path separator ( '\/' i.e. '/' but escaped, because is the same separator used in this regex), then capture (and put it in $1) followed by anychar one time ( '.' ERROR: the dot must be escaped if you want a real lonely dot!) and endly a 'lib' string. All the matched string will be subsituted by what is in the captured variable ($1).

    But YAPE::Regex::Explain is our friend!

    perl -MYAPE::Regex::Explain -e "my $rex = qr(s/.*\/(.*).lib/$1/); prin +t YAPE::Regex::Explain->new($rex)->explain" The regular expression: (?-imsx:s/.*\/(.*).lib//) 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): ---------------------------------------------------------------------- s/ 's/' ---------------------------------------------------------------------- .* any character except \n (0 or more times (matching the most amount possible)) ---------------------------------------------------------------------- \/ '/' ---------------------------------------------------------------------- ( group and capture to \1: ---------------------------------------------------------------------- .* any character except \n (0 or more times (matching the most amount possible)) ---------------------------------------------------------------------- ) end of \1 ---------------------------------------------------------------------- . any character except \n ---------------------------------------------------------------------- lib// 'lib//' ---------------------------------------------------------------------- ) end of grouping ----------------------------------------------------------------------

    L*
    UPDATE: as stated by wise monks below the module does not handle substitutions and in the case above produce somehow misleading output (as lib//). So better to reduce the regex to a non substituiton one and inspect the output to see where the error is (at the dot).
    perl -MYAPE::Regex::Explain -e "print YAPE::Regex::Explain->new('.*\/( +.*).lib')->explain" The regular expression: (?-imsx:.*\/(.*).lib) 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 except \n (0 or more times (matching the most amount possible)) ---------------------------------------------------------------------- \/ '/' ---------------------------------------------------------------------- ( group and capture to \1: ---------------------------------------------------------------------- .* any character except \n (0 or more times (matching the most amount possible)) ---------------------------------------------------------------------- ) end of \1 ---------------------------------------------------------------------- . any character except \n ---------------------------------------------------------------------- lib 'lib' ---------------------------------------------------------------------- ) end of grouping ----------------------------------------------------------------------
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      YAPE::Regex::Explain doesn't handle substitutions, it can only explain regular expressions. Substitution is a regular expression plus pattern to replace the matching part, the pattern usually works as double quoted string (unless /e is involved).
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        yes, you are right choroba and in fact in the explanation given there is no mention of the substitution. Anyway it handles correctly the interesting part and also in this case helps a lot in spotting the wrong part.

        L*
        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Regex explanation
by hippo (Archbishop) on Sep 14, 2015 at 08:38 UTC

    Sure. It looks for the phrase 'lib' more than 1 character after a slash. If that is found then it replaces everything up to and including the 'lib' with what was between the slash and the character before the 'lib'. The expression to be matched against (and altered) is in $lib_name.

    eg. if the expression were 'foo/barlib' the result would be 'ba'

Re: Regex explanation
by Your Mother (Archbishop) on Sep 14, 2015 at 12:33 UTC

    FWIW, it's a poorly crafted regex. It will make false matches; e.g.–

    moo@cow>perl -le 'print "MATCH" if +shift =~ /.*\/(.*).lib/' ' /ohai/l +ib/bingo' MATCH moo@cow>perl -le 'print "MATCH" if +shift =~ /.*\/(.*).lib/' 't a c o/ +alibrary.mp4' MATCH

    I presume it is meant to match and retain the plain lib name. This is saner but maybe not as good as it gets–

    $lib_name =~ s{\A.+/([^/]+)\.lib\z}{$1};

    I left out dot-star because you should if you can and if we know there will always be a slash before the lib (/lib) then we can assume there will always be *some* content before the slash (c.f., there is never going to be a volume:/lib dir). Lots more info: perlre.