Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

string substitution

by Anonymous Monk
on Oct 08, 2003 at 16:04 UTC ( [id://297642]=perlquestion: print w/replies, xml ) Need Help??

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

Hello dear Monks, I am trying to do some substitution like: $newstring=~ s/BAD/HELL/g

My issue is that I only want to substitue HELL for BAD when HELL is flanked on either side by an arithmetic operator, space, or paren (or it's the stort of the line: i.e.:

+HELL

HELL/

HELL)

(HELL<

thanks, me

Replies are listed 'Best First'.
Re: string substitution
by Not_a_Number (Prior) on Oct 08, 2003 at 18:04 UTC

    Assuming "on either side" to mean "on both sides" (see my post above), try this awfully ugly code:

    use strict; use warnings; my $ariths = quotemeta '()+</*><-'; while ( <DATA> ) { s/(?:(?:(?<=[$ariths])BAD)|^BAD)(?=[$ariths])/HELL/g; print; } __DATA__ +BAD # No BAD/ # Yes BAD) # Yes (BAD<) # Yes BAD # No BADGER # No BADGER+ # No +SINBAD+ # No BAD (BAD+ # No then Yes

    Improvements welcome!

    dave

    Update: davido's corrected regex above already represents a significant improvement!

      Sorry for the late reply

      Basically, this:

      $string="HELL +HELL +(HELL) + (HELL) + ( HELL ) REALHELL REALHELL HELL +";

      Should be changed to this:

      BAD +BAD +(BAD) + (BAD) + ( BAD ) REALHELL REALHELL BAD

        $string =~ s/\bHELL\b/BAD/g; $string =~ s/(?<\W)\s|\s(?=\W)//g;
        First pass does the HELL -> BAD substitution based on word boundries. So far none of your examples have shown characters that are not either mathematical symbols, alpha, or space. So I'm not going to waste your time with worrying about whether BAD is next to a mathematical symbol. If your examples showed non-mathematical symbols, then I'd worry about that part again.

        The second pass removes any whitespace that has a non-word character on one side or the other of it. That will get rid of the space between BAD and +, but not between REALHELL and REALHELL.

        Until we know what you're really trying to do we will continue playing the guessing game and falling short of your needs. Be sure to read perlretut and perlre. It's your turn to come up with a solution.


        Dave


        "If I had my life to do over again, I'd be a plumber." -- Albert Einstein
Re: string substitution
by fletcher_the_dog (Friar) on Oct 08, 2003 at 17:02 UTC
    I may be wrong, but it sounds like you only want to replace BAD with HELL when BAD is a whole word.(e.g. you don't want "BADGER" to become "HELLGER"). If that is the case you might want to look at "\b" in "perldoc perlre"
Re: string substitution
by mandog (Curate) on Oct 08, 2003 at 16:35 UTC

    What is the problem this is solving ?

    You might consider a charactor class a boolean "or" and a start-of-line marker. See perldoc perlre for details

Re: string substitution
by davido (Cardinal) on Oct 08, 2003 at 17:34 UTC
    Here's one that works without capturing parens and backreferences.
    my $ariths = '(+*\-/<>=)%^'; $string =~ s/(?:^|(?<=[$ariths]))BAD(?=[$ariths])/HELL/g;
    There may be a better way to do it though. Consider \b for word boundries.

    Update:Ugg, thanks Not_a_Number... corrected. I used a non-capturing paren when I meant to use a zero-width assertion.


    Dave


    "If I had my life to do over again, I'd be a plumber." -- Albert Einstein

      But that:

      1) removes the arithmetic operators;

      2) doesn't meet the 'start of line' spec.

      :-(

      dave

      Fixed. I shouldn't post Regexp nodes before eating my breakfast cereal.

      For the record:
      1. I mistakenly used (?: ) non-capturing parens when I meant to use (?<= ) and (?= ) zero-width assertions.
      2. I didn't realize that stort meant start.

      The issues have been resolved. :)


      Dave


      "If I had my life to do over again, I'd be a plumber." -- Albert Einstein
Re: string substitution
by seaver (Pilgrim) on Oct 08, 2003 at 16:20 UTC
    Something like this (untested):

    $newstring =~ s/([+<-/)*>])HELL([+<-/)*>])/$1BAD$2/g;
    You need the $1 and $2 to retain your symbols. update symbols between square brackets according to your wishes

    Cheers
    Sam

      Greetings seaver

      you might escape some of the chars in your char class.

      For example, inside a char class '-' is a range operator. [a-e] instead of [abcde]

      Also it is hard to tell the paren inside your char class from the first closing paren

Re: string substitution
by Not_a_Number (Prior) on Oct 08, 2003 at 17:28 UTC

    Could you elucidate? As a native English speaker, I would tend to interpret "flanked on either side by an X" as "having an X on both sides", as in "flanked on either side by a policeman".

    In which case, your first example:

    +HELL

    should remain unchanged. Is this what you mean?

    dave

      Sorry, On either side means could be on 0, one, or both. I **do** think you interpreted correctly, I just didn't **type** correctly.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2024-03-29 10:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found