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

I'm trying to remove everything from a variable, let's call it $data, that occurs before the FIRST occurence of a word. When I do it it removes everything up to the last occurence of it and it is messing up the data I am working with.

I am using
$data =~ s/.+TEST/TEST/;
I want everything removed from the first occurence of whatever my word is, in the example above it is TEST. I know there must be a way to do this without having to subsitute the word back in, right? Can you help me?

Replies are listed 'Best First'.
Re: How do you make a regex non greedy
by GrandFather (Saint) on Mar 20, 2011 at 04:53 UTC

    It's important to anchor both ends of a non-greedy match because the minimum that can be matched is nothing at all.

    use strict; use warnings; my $str = "Some rubbish before TEST and the good stuff afterwards"; $str =~ s/^.*?(?=TEST)//; print $str;

    Prints:

    TEST and the good stuff afterwards

    Not too the use of (?=TEST) which is a zero width look ahead match. It matches TEST, but doesn't consume it so you don't need to replace it later.

    True laziness is hard work
Re: How do you make a regex non greedy
by Anonymous Monk on Mar 20, 2011 at 03:33 UTC
    use *? instead of *

      Not so simple. You have also to anchor the left hand end:

      s/^.*?TEST/TEST/

      Update: Argh - one day I'll stop getting bitten by that! Anonymous Monk is quite right. No backtracking is required to get a match so .*? matches everything from the start or the string up to TEST - no anchor needed.

      True laziness is hard work
        Yes, it is precisely that simple
        $_ = '1 TEST 2 TEST 3 TEST'; s/.*?TEST/TEST/; print; __END__ TEST 2 TEST 3 TEST
Re: How do you make a regex non greedy
by wind (Priest) on Mar 20, 2011 at 04:23 UTC

      Not so simple. You have also to anchor the left hand end:

      s/^.*?(?=TEST)//

      Update: Argh - one day I'll stop getting bitten by that! Anonymous Monk is quite right. No backtracking is required to get a match so .*? matches everything from the start or the string up to TEST - no anchor needed.

      True laziness is hard work
        Anchoring isn't needed here either
        $_ = '1 TEST 2 TEST 3 TEST'; s/.*?(?=TEST)//; print; __END__ TEST 2 TEST 3 TEST