http://qs321.pair.com?node_id=307617

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

Hello Monks !

Let's define the example first :-) I have following two texts :

- John is following jane
- John is following Jane

Yes, the only difference is the capital 'J'. Now my question: I'd like to replace both occurences of 'Jane' with let's say '##Jane##'. The search should be case insensitive but the replace should be case sensitive.

So the result in this example should be :

- John is following ##jane##
- John is following ##Jane##

Is this solvable with a regex ?

Many many thanks for your help !

Dany

  • Comment on Regex: Case insensitive search but case sensitive replace

Replies are listed 'Best First'.
Re: Regex: Case insensitive search but case sensitive replace
by Limbic~Region (Chancellor) on Nov 17, 2003 at 10:29 UTC
    Anonymous Monk,
    The answer is yes, but you probably want something for the general case as well as this specific case.
    #!/usr/bin/perl -w use strict; my $string = 'John is following jane'; # Specific $string =~ s/[jJ]ane/##Jane##/; # To preserve j or J in replacement # $string =~ s/([jJ]ane)/##$1##/; # More generic # $string =~ s/(John is following) (\w+)/$1 \u$2/;
    Cheers - L~R

      Thx L~r !

      But the generic version would replace both 'jane' & 'Jane' with 'Jane'.

      I'm looking for a way to search insensitive but the replace should keep the case of the word/text ...

      Thx again !

        Anonymous Monk,
        I provided 3 examples because you were not exactly clear what your definition of "case insensitive" and "case sensitive" was in your post. The second example is closest to what you mean, but you might have also meant:
        $string =~ s/(jane)/##$1##/i;
        This would allow any letters to be any case, but be preserved in the replacement.

        Cheers - L~R

Re: Regex: Case insensitive search but case sensitive replace
by Abigail-II (Bishop) on Nov 17, 2003 at 12:26 UTC
    Well, replacing 'Jane' (any case) with '##Jane##' (same case) is trivial: s/(jane)/##$1##/ig; will do.

    But let's say you want to replace 'Jane' (any case) with 'Mary' (same case). Here's one way of doing it:

    #!/usr/bin/perl use strict; use warnings; my $pat = "jane"; my $repl = "mary"; while (<DATA>) { s/($pat)/$1 ^ $pat ^ $repl/eig; print; } __DATA__ jane janE jaNe jaNE jAne jAnE jANe jANE Jane JanE JaNe JaNE JAne JAnE JANe JANE mary marY maRy maRY mAry mArY mARy mARY Mary MarY MaRy MaRY MAry MArY MARy MARY

    Abigail

Re: Regex: Case insensitive search but case sensitive replace
by ehdonhon (Curate) on Nov 17, 2003 at 11:54 UTC

    If you use the /i switch in combination with 's///', it will capture any case permutation of whatever it is you are replacing, and if you use that captured text, it will appear in the exact same case permutation as it was captured. This will work no matter what you are trying to capture.

    while ( chomp( my $line = <DATA> ) ) { $line =~ s/(Fred)/"$1"/i; print "$^C root@who1# perl while ( my $line = <DATA> ) { $line =~ s/(Fred)/"$1"/i; print $line; } __DATA__ Hello, my name is FRED! fREd went to the store. Nobody was home, except for freD.

    Output:

    Hello, my name is "FRED"!
    "fREd" went to the store.
    Nobody was home, except for "freD".
    

    You mention in a later post that you are looking for something more generic that will work for anything, not just names. Perhaps this is what you are looking for?

    my $tag = 'jane'; while ( <DATA> ) { s/($tag)/##$1##/i; # you might also want a /g here as well. print; } __DATA__ - John is following jane - John is following Jane

    Output:

    - John is following ##jane##
    - John is following ##Jane##
    
Re: Regex: Case insensitive search but case sensitive replace
by delirium (Chaplain) on Nov 17, 2003 at 10:39 UTC
    {using corny Get Smart accent} Missed it by that much.
    Anyway, here's mine, using /i switch:

    perl -le '$t="John is following jane"; $t=~s/(jane)/##$1##/i; print $t +' John is following ##jane## $perl -le '$t="John is following Jane"; $t=~s/(jane)/##$1##/i; print $ +t' John is following ##Jane##
Re: Regex: Case insensitive search but case sensitive replace
by ysth (Canon) on Nov 17, 2003 at 10:37 UTC
    Replacements are always done with exactly the case you specify, so s/jane/###Jane###/i will replace any of JaNe, janE, JAne, etc with ###Jane###.

    If you mean you want to capture some names and replace them having a capital letter first and lower thereafter, try something like s/(j\wn\w)/"###".ucfirst(lc($1))."###"/ie

    Update: That turns out not to be the answer to the question the seeker was trying to ask. However, you can also do the above this way: s/($name)/###\u\L$1###/i

Re: Regex: Case insensitive search but case sensitive replace
by Anonymous Monk on Nov 17, 2003 at 10:42 UTC
    Sorry, guess i was a bit imprecisely :-)

    I'm looking for a way to change any kind of text (not only names) ...

    I really appreciate your help !

    Dany
Re: Regex: Case insensitive search but case sensitive replace
by Anonymous Monk on Nov 17, 2003 at 12:16 UTC
    Thx for all this tips !

    The following regex perfectly fits my needs :

    $string =~ s/(anything)/##$1##/i

    Thx again for your help !
    Dany
Re: Regex: Case insensitive search but case sensitive replace
by Hena (Friar) on Nov 17, 2003 at 12:09 UTC
    Hard, but this seems to work
    $a="John is following jane"; $a=~s/(jane)/ucfirst(lc($1));/iee; print "$a\n";
    We do evaluation on right side of the substitution. With '#' in there it didn't work (might need more figuring out).