Podrías usar perl
. Directamente de las preguntas frecuentes - citando perldoc perlfaq6
:
¿Cómo puedo sustituir mayúsculas y minúsculas en el LHS mientras se preserva el caso en el RHS?
Aquí hay una hermosa solución Perlish de Larry Rosler. Explota las propiedades de bit xor en cadenas ASCII.
$_= "this is a TEsT case";
$old = 'test';
$new = 'success';
s{(\Q$old\E)}
{ uc $new | (uc $1 ^ $1) .
(uc(substr $1, -1) ^ substr $1, -1) x
(length($new) - length $1)
}egi;
print;
Y aquí está como una subrutina, modelada a partir de lo anterior:
sub preserve_case($$) {
my ($old, $new) = @_;
my $mask = uc $old ^ $old;
uc $new | $mask .
substr($mask, -1) x (length($new) - length($old))
}
$string = "this is a TEsT case";
$string =~ s/(test)/preserve_case($1, "success")/egi;
print "$string\n";
Esto imprime:
this is a SUcCESS case
Como alternativa, para mantener el caso de la palabra de reemplazo si es más larga que la original, puede usar este código, por Jeff Pinyan:
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);
}
Esto cambia la oración a "este es un caso de ÉXITO".
Solo para mostrar que los programadores de C pueden escribir C en cualquier lenguaje de programación, si prefiere una solución más similar a C, el siguiente script hace que la sustitución tenga el mismo caso, letra por letra, que el original. (También sucede que se ejecuta aproximadamente un 240% más lento que la solución Perlish). Si la sustitución tiene más caracteres que la cadena que se sustituye, el caso del último carácter se utiliza para el resto de la sustitución.
# Original by Nathan Torkington, massaged by Jeffrey Friedl
#
sub preserve_case($$)
{
my ($old, $new) = @_;
my ($state) = 0; # 0 = no change; 1 = lc; 2 = uc
my ($i, $oldlen, $newlen, $c) = (0, length($old), length($new));
my ($len) = $oldlen < $newlen ? $oldlen : $newlen;
for ($i = 0; $i < $len; $i++) {
if ($c = substr($old, $i, 1), $c =~ /[\W\d_]/) {
$state = 0;
} elsif (lc $c eq $c) {
substr($new, $i, 1) = lc(substr($new, $i, 1));
$state = 1;
} else {
substr($new, $i, 1) = uc(substr($new, $i, 1));
$state = 2;
}
}
# finish up with any remaining new (for when new is longer than old)
if ($newlen > $oldlen) {
if ($state == 1) {
substr($new, $oldlen) = lc(substr($new, $oldlen));
} elsif ($state == 2) {
substr($new, $oldlen) = uc(substr($new, $oldlen));
}
}
return $new;
}
ABcDeF
?