http://qs321.pair.com?node_id=764934

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

I cain't figger it out! Would anyone take pity on poor dumb 8@$+@40? Of course, no comments were found to explain what this Perl snippet does:
($bname = $fname) =~ s#.*\\##s;

Replies are listed 'Best First'.
Re: Assign Contains RegEx WTF??
by kennethk (Abbot) on May 19, 2009 at 15:09 UTC
    This snippet does the following:
    1. Copies the contents of $fname to $bname
    2. Binds the regular expression to $bname
    3. Removes everything up to the final backslash ( \ ) from the string stored in $bname. Specifically, this expression (using the alternate delimiter '#') greedily matches any number of any characters (.*) followed by a backslash (which must be escaped, thus \\).

    So the string 'C:\folder\file' would be transformed to 'file'.

    All the details needed to parse the regular expression can be found in perlre and/or prelretut.

      Thank you wise monk(s)! My confusion has blossomed into amusement. The original "programmer" was only good at "pasting".

      Original code:
      $fname = $TMP_DIR . "\\" . $tnum . ".tmp"; ($bname = $fname) =~ s#.*\\##s;
      New code: (terseness removed)
      $bname = $tnum . ".tmp"; $fname = $TMP_DIR . "\\" . $bname;
        If you are just modifying paths, you may consider using the File::Spec module. May very well be overkill for your app, though.
Re: Assign Contains RegEx WTF??
by ikegami (Patriarch) on May 19, 2009 at 15:25 UTC

    It's just like ($x + $y) * $z. The contents of the parens are evaluated first, and the result is used as the operand of the operation outside the parens.

    Scalar assignment returns its LHS as an lvalue, so

    ($bname = $fname) =~ s#.*\\##s;
    is the same as
    $bname = $fname; $bname =~ s#.*\\##s;

      I just wanted to say thanks, I'd seen that before, and knew what it was and meant, but it never clicked before and this made it click! ;)


      ___________
      Eric Hodges
Re: Assign Contains RegEx WTF??
by davido (Cardinal) on May 19, 2009 at 15:42 UTC

    It looks like needlessly terse code to me even though it probably works great. Relying on ($bname = $fname) to bind the lefthand value ($bname) with the RE is accurate, but it's difficult to read. The substitution regular expression isn't all that hard to read, but should have been documented, although then you would have:

    s#.*\\##s; # comments here.

    So perhaps a different delimiter would have been prudent. Why not: s{.*\\}[]s # comments here? It would be a little more legible, and could tell the reader what's going on. Of course there's always YAPE::Regex::Explain that can get you out of a bind when things get cryptic.


    Dave

      It looks like needlessly terse code to me even though it probably works great.
      I've seen enough code by enough people doing this, that's it's idiom to me.

      But then, most idiom will look like needlessly terse code to beginners.

        How does the quote go? "Any sufficiently advanced technology is indistinguishable from magic." (Or something along those lines.)

        Anyway, if the point is to write maintainable code, it still seems reasonable to document well enough that the intent is clear. Code comments aren't only for beginners. They also serve to illustrate to future maintainers that "you really did mean to do that." Plus, they will help to save time as someone else familiarizes him/herself with your code. Or is that "h(?:im|er)self"? ;)


        Dave