Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Regex to get everything before first /

by limzz (Novice)
on Jun 06, 2011 at 18:45 UTC ( #908348=perlquestion: print w/replies, xml ) Need Help??

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

Please help, I've spent over an hour trying to figure out how to take everything before the first forward slash in a string. It's consuming my sanity and I don't think I or my monitor will survive much longer.

(my $stuff) = ($thing =~ /^(\S+)\/*?/)

I've tried every variation on that line I can think of and none of them worked. Someone please save me before I lose my mind.

Replies are listed 'Best First'.
Re: Regex to get everything before first /
by davido (Cardinal) on Jun 06, 2011 at 19:18 UTC

    toolic hit the nail on the head, but you might choose a different delimiter so that it wouldn't be necessary to escape the forward slash, like this:

    my $thing = 'foo/bar/goo'; ( my $stuff ) = ( $thing =~ m{ # Quote-like characters are now {}. ^ # Match at the start of the string. ( [^/]+ ) # Capture everything in the set of all # characters that are not '/' }x # Close the regexp. x modifier allows # freeform (as in non-significant # whitespace). ); print "$stuff\n";

    The m{} brackets avoid the leaning toothpick syndrome in the original regexp. Of course if you were matching against a curly bracket the curly brackets wouldn't be all that wonderful as quote delimiters, but for this regexp they work out well. /x modifier added to allow comments and insignificant whitespace (it makes everything prettier).


    Dave

      /x modifier added to allow comments and insignificant whitespace (it makes everything prettier).
      And it's easy to get carry it too far. I find /([^\/]*)/ far superior to your novella.

      There's a guide line to not overdo comments. That's, don't do:

      $i++; # Increment $i by one, or to the next "word".
      That holds for patterns as well.

        I see a difference between explaining what I'm doing to someone who was having difficulty with a fairly straightforward regexp, in the context of a learning environment, and producing clear, concise, readable code in a non-instructional environment. A novella to an experienced user may be useful guidance to someone with less familiarity on the topic.

        It could also be said that YAPE::Regex::Explain produces too much explanation. Yet when it's requested, it's available. Should someone comment the trivial in a normal script (whatever normal means)? No. Could excessive comments be helpful in the context of describing how a specific segment of code works to someone who has requested instruction? Yes.

        Anyway, the code and comments were provided with the intent of being helpful, and I believe that goal was probably accomplished.


        Dave

        A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Regex to get everything before first /
by toolic (Bishop) on Jun 06, 2011 at 18:59 UTC
    How's this:
    use warnings; use strict; my $thing = 'foo/bar/goo'; (my $stuff) = ($thing =~ /^([^\/]+)/); print "$stuff\n"; __END__ foo

      I love you.

Re: Regex to get everything before first /
by wind (Priest) on Jun 06, 2011 at 19:39 UTC

    One final addition to toolic and davido's posts:

    You might as well make it match {0,} instead of {1,} so that strings that start with / will equal the empty string instead of undef.

    This way you can avoid "Use of uninitialized value in concatenation (.)" warnings.

    use warnings; use strict; my $thing = 'foo/bar/goo'; my ($stuff) = $thing =~ m{^([^/]*)}; print "$stuff\n"; __END__ foo
Re: Regex to get everything before first /
by ikegami (Pope) on Jun 06, 2011 at 19:44 UTC
    my ($stuff) = $thing =~ m{^([^/]*)};
    my ($stuff) = $thing =~ m{^(.*?)/}s;
    my ($stuff) = split(qr{/}, $thing, 2);
    my ($stuff) = split(qr{/}, $thing);

    The second requires the presence of a "/", and uses the non-greedy modifier which I prefer to avoid.

      the non-greedy modifier which I prefer to avoid
      For what reason(s)?

        It fails poorly when there's a problem because the /.*?/ in /.*?// can match "/". It's only indirectly through co-operation with the rest of the pattern that it might be prevented from doing so. I prefer being more direct and explicitly prevent what should not be matched from matching.

      Another one:

      my ($stuff) = $thing =~ m{[^/]*}g;
Re: Regex to get everything before first /
by planetscape (Chancellor) on Jun 06, 2011 at 22:21 UTC

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2020-11-26 21:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?