Vous pourriez utiliser perl
. Directement à partir de la FAQ - citant perldoc perlfaq6
:
Comment puis-je remplacer la casse de manière insensible sur le LHS tout en préservant la casse sur le RHS?
Voici une belle solution Perlish de Larry Rosler. Il exploite les propriétés de xor au niveau du bit sur les chaînes 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;
Et ici, c'est comme un sous-programme, calqué sur ce qui précède:
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";
Cela imprime:
this is a SUcCESS case
Comme alternative, pour conserver la casse du mot de remplacement s'il est plus long que l'original, vous pouvez utiliser ce code, par 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);
}
Cela change la phrase en "ceci est un cas de SUCESS."
Juste pour montrer que les programmeurs C peuvent écrire C dans n'importe quel langage de programmation, si vous préférez une solution plus semblable à C, le script suivant fait que la substitution a le même cas, lettre par lettre, que l'original. (Il se trouve également qu'il s'exécute environ 240% plus lentement que la solution Perlish.) Si la substitution a plus de caractères que la chaîne substituée, la casse du dernier caractère est utilisée pour le reste de la substitution.
# 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
?