Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Regular Expression

by ashok (Sexton)
on Jan 16, 2001 at 10:16 UTC ( [id://52173]=perlquestion: print w/replies, xml ) Need Help??

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

Hi , It is very simple. But I am struggling. I want to replace a part of the string with blank after matching for first occurence only. Like this:
$_ = "text1 text2 -f -DFLAG1 -global -DFLAG2 -DFLAG1"; $str = s/.*\-D*?//; print "$_\n";
I want the o/p should be "-DFLAG1 -global -DFLAG2 -DFLAG1". But I am getting DFLAG1. Can you pl. help me? Thanks Ashok

Replies are listed 'Best First'.
(Ovid) Re: Regular Expression
by Ovid (Cardinal) on Jan 16, 2001 at 10:46 UTC
    You have a few problems here that we can clear up. First, you need to use warnings. Either include -w on the shebang line of your script:
    #!/usr/bin/perl -w
    Or use the "warnings" pragma if your version of Perl supports it:
    use warnings;
    These will tell you that "$main::str" was used only once, which can help you see that you have a typo in the following line:
    $str = s/.*\-D*?//;
    Further, 'use strict;' will catch errors like that.

    You probably meant for $str to be $_. Also, you have an equals '=' sign when you want the regex binding operator: '=~'. The reason you are getting output is because your regular expression is evaluating against the value of $_ and you are throwing away the value of $str. You can either leave off the '$str =' part, or change the code to the following:

    $_ = "text1 text2 -f -DFLAG1 -global -DFLAG2 -DFLAG1"; s/.*?(?=-D)//; print "$_\n";
    The (?=-D) uses a positive lookahead. That checks to see if it matches data, but doesn't include that data in the text that is matched. See perlre for more information on this.

    Also, I don't like the dot star in this regular expression. If your data is likely to always be in this format, try the following:

    s/[^-]+-[^-]+//;
    However, that regex looks a bit obscure. If this is not a time-sensitive script, you may want to stick with the first one. See Death to Dot Star! for information on problems with the dot star '.*' combination in regexes.

    That regular expression, broken out with the /x modifier, reads like this:

    s/ [^-]+ # Negated character class - match one or more # of anything that is not a dash: "text1 text2 " - # match the dash: "-" [^-]+ # Negated character class - match one or more # of anything that is not a dash: "f " //x;
    No offense, but you seem to have some troubles with English. Since this answer is a bit complicated, feel free to e-mail me at poec@yahoo.com if you have any questions.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: Regular Expression
by chipmunk (Parson) on Jan 16, 2001 at 10:33 UTC
    The initial .* takes the regex all the way to the end of the string; then it backtracks just far enough to match the -D closest to the end. One solution is to change the substitution to: $str =~ s/.*?(?=-D)//; The non-greedy matching moves forward one character at a time, until -D matches. Because the -D is in a positive lookahead assertion, it's not used up as part of the match, so it doesn't need to be replaced on the right hand side.

    Another approach is to match what you want and pull it out: ($args) = $str =~ /(-D.*)/;

      Yes, It works. Great. Thanks
Re: Regular Expression
by dkubb (Deacon) on Jan 16, 2001 at 11:03 UTC
    It might be easier to use perl's built in routines substr and index:
    my $string = 'text1 text2 -f -DFLAG1 -global -DFLAG2 -DFLAG1'; my $pattern = '-D'; print substr($string, index($string, $pattern)), "\n";

    index() returns the position, in the $string, of the first occurent of $pattern. Then substr uses the position to return everything after it inside $string. This should be simpler and much faster than using a .* regex.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (7)
As of 2024-04-18 17:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found