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

I'd like to perform a search and replace regular expression which preserves the case of the word as best as possible using the following rules:

What's the best way to do this? I can think of some ugly hacks that check the case of the word, set a flag, and then adjust it afterwards. But I assume there's a better way.

Any Regexp gurus out there with good ideas?

  • Comment on Case-preserving regexp search and replace?

Replies are listed 'Best First'.
Re: Case-preserving regexp search and replace?
by japhy (Canon) on Aug 26, 2001 at 21:03 UTC
    I'd suggest checking perlfaq6, question five. I added a solution to it, which will appear in some future Perl:
    $_ = "this is a TEsT case"; s/(test)/preserve_case($1, "success")/egi; sub preserve_case { my ($from, $to) = @_; my ($lf, $lt) = map length, @_; if ($lt < $lf) { $from = substr $from, 0, $lt } else { $from .= substr $to, $lf } return uc $to | ($from ^ uc $from); }

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      I tried it, and it doesn't work as needed: I need it to match the case of the last letter. So if I want to replace "FOOBAR" with "whatever", it will return "WHATEVer" instead of "WHATEVER".

      Newever versions of the Regexp FAQ have some routines not online here that do that fiddling with bits in ASCII. Not necessarily Unicode compliant but neat tricks nontheless.

        If you want to keep the case of the last letter, then the other solution in perlfaq6 is what you want.

        _____________________________________________________
        Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
        s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Case-preserving regexp search and replace?
by chipmunk (Parson) on Aug 26, 2001 at 21:50 UTC
Re: Case-preserving regexp search and replace?
by dga (Hermit) on Aug 26, 2001 at 21:19 UTC

    Not sure what you are needing this to do but the following would preserve clarity as to what was going on.

    #in a loop s/[A-Z]+/REPLACE/, next; s/[a-z]+/replace/, next; s/[A-Z][a-z]+/Replace/, next;

    If its simple letter translation you could of course use tr/// which would keep your cases straight.