Puoi usare perl
. Direttamente dalla domanda frequente - citando da perldoc perlfaq6
:
Come posso sostituire il case insensitive sull'LHS preservando il case sull'RHS?
Ecco una deliziosa soluzione Perlish di Larry Rosler. Sfrutta le proprietà di xor bit a bit sulle stringhe 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;
Ed eccolo come una subroutine, modellato su quanto sopra:
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";
Questo stampa:
this is a SUcCESS case
In alternativa, per mantenere il caso della parola sostitutiva se è più lunga dell'originale, è possibile utilizzare questo codice, di 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);
}
Questo cambia la frase in "questo è un caso SUcCess".
Solo per dimostrare che i programmatori C possono scrivere C in qualsiasi linguaggio di programmazione, se si preferisce una soluzione più simile al C, il seguente script fa sì che la sostituzione abbia lo stesso caso, lettera per lettera, dell'originale. (Succede anche che sia più lento del 240% circa rispetto alla soluzione Perlish.) Se la sostituzione ha più caratteri della stringa sostituita, il caso dell'ultimo carattere viene usato per il resto della sostituzione.
# 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
?