duckworthd
duckworthd

Reputation: 15207

How to Replace Text while Maintaining Capitalization?

Say I wanted to a string replace on a file with the following contents

name
nAmE
naMEbb
NAME

And wanted to replace the word "name" with "dave", but keeping the capitalization of the original text. For example, my desired output would be,

dave
dAvE
daVEbb
DAVE

Are there any one-liners to do this (preferably in Perl so I can do an in-place substitution across many files)?

EDIT The problem is ambiguous unless both strings have exactly the same length. Let's assume it does.

Upvotes: 8

Views: 338

Answers (3)

Raimund Steger
Raimund Steger

Reputation: 69

I wonder whether the example from perlfaq works for non-ASCII. A variant that doesn't use the XOR hack could be:

$text =~ s{$str_to_replace}{my $i=0;join "",map {substr($&,$i++,1)=~/\p{IsLower}/?lc:uc} split //,$str_to_substitute}ieg;

But this only works if the /i modifier is locale-enabled (see perllocale).

Upvotes: 0

Tomas
Tomas

Reputation: 59483

It's crazy but it works:

perl -e 'use List::MoreUtils "pairwise"; $_ = "toto naME nAmE"; s/(name)/@x = map(ord, split "", "DAVE"); @y = map(ord>=97?32:0, split "", $1); @c = map chr, pairwise { $a + $b } @x, @y; $" = ""; "@c";/gei; print "$_\n";'

one line solution!

Upvotes: 0

mMontu
mMontu

Reputation: 9273

There are some solutions on perlFaq: http://perldoc.perl.org/perlfaq6.html#How-do-I-substitute-case-insensitively-on-the-LHS-while-preserving-case-on-the-RHS?

One of solutions presented there allows to perform the substitution in a single line, by defining a subroutine (preserve_case):

   $string = "this is a TEsT case";
   $string =~ s/(test)/preserve_case($1, "success")/egi;
   print "$string\n";

This prints: this is a SUcCESS case

Upvotes: 8

Related Questions