2010-01-29 8 views
1

Comment puis-je rechercher et remplacer une correspondance avec un nombre spécifique de fois en utilisant s///;. Par exemple:Comment puis-je rechercher et remplacer un nombre spécifique de fois dans une chaîne en Perl?

$string="abcabdaaa"; 

Je veux remplacer a avec i dans $string n fois. Comment puis je faire ça? n est un nombre entier fourni par l'utilisateur.

+2

Les réponses à cette question sont fournis aussi à un autre forum: http://www.perlmonks.org/?node_id=820332 – toolic

+0

Pouvez-vous expliquer un peu plus sur ce que vous êtes Faire? Vous avez un peu un problème XY ici. Dites-lui d'utiliser le vrai problème que vous essayez de résoudre au lieu de la solution potentielle que vous pensez être la réponse. :) –

Répondre

4

Je ne suis au courant d'aucun drapeau qui ferait cela. Je voudrais simplement utiliser une boucle:

for (my $i = 0; $i < $n; $i++) 
{ 
    $string =~ s/a/i/; 
} 
6

seulement $ substituez n fois:

$string =~ s/a/i/ for 1..$n; 

Cela fera.
solution plus générale serait substitution globale avec contre:

my $i = 0; # count the substitutions made 
$string =~ s/(a)/ ++$i > $n ? $1 : "i" /ge; 
+0

Salut mais je suis confronté à un problème lors du remplacement par $ s = "*** ab *** c"; $ s = ~ s {\ *} {\ * \ n} pour 1..2; imprimer $ s; il remplace d'abord * par * \ n et le reste il ignore ... pourquoi? "* \ n" ** ab *** c – User1611

+0

Si je vous comprends bien, vous avez besoin de ceci comme suit: my $ i = 0; $ str = ~ s/(\\ *)/++ $ i> $ n? 1 $: "* \ n"/ge; –

4

vous pouvez essayer ceci:

$str1=join('i',split(/a/,$str,$n)); 
+0

Je crois que ce serait plus efficace que de simplement faire $ string = ~ s/a/i/pour 1 .. $ n; – jojo

+0

Veuillez expliquer pourquoi vous croyez que c'est plus efficace. Vous créez inutilement 2 variables temporaires supplémentaires ('$ str1' et' @ arr').Vous pourriez le simplifier comme '$ str = rejoindre 'i', split/a /, $ str, $ n;', mais je ne pense pas que ce soit aussi facile à comprendre que la solution 's ///'. – toolic

+2

vous pouvez avoir raison sur le facile à comprendre. mais en ce qui concerne l'efficacité en utilisant s/a/i/pour 1 .. $ n prendra O (n * m). tandis que l'utilisation de split prendra O (n). – jojo

9

La réponse simple ne probablement ne veux pas que vous voulez.

my $str = 'aaaa'; 
$str =~ s/a/a_/ for 1..2; 
print $str, "\n"; # a__aaa. But you want a_a_aa, right? 

Vous devez compter les remplacements vous, et agir en conséquence:

$str = 'aaaa'; 
my $n = 0; 
$str =~ s/(a)/ ++$n > 2 ? $1 : 'a_' /ge; 
print $str, "\n"; 

Voir la FAQ, How do I change the Nth occurrence of something? des exemples connexes.

0

En utilisant

sub substitute_n { 
    my $n = shift; 
    my $pattern = shift; 
    my $replace = shift; 
    local $_ = shift; 

    my $i = 1; 
    s{($pattern)} { 
    $i++ <= $n ? eval qq{"$replace"} : $1; 
    }ge; 

    $_; 
} 

Vous pouvez alors écrire

my $s = "***ab***c"; 

print "[", substitute_n(2, qr/\*/, '$1\n', $s), "]\n"; 

pour obtenir la sortie suivante:

[* 
* 
*ab***c]
+0

La sortie ne sera-t-elle pas réellement: [* \ n \ n ** ab *** c]? Il apparaîtra sur le premier * à chaque itération. –

+0

J'ai posté runnable, le code de travail. Tu n'as pas à me croire sur parole! :-) –

1

Voici une façon de le faire sur la base du commentaire que vous avez fait à eugene y's answer

#!/usr/bin/perl 

use strict; use warnings; 

my $string = '***ab***c'; 
my $n = 3; 

1 while $n -- and $string =~ s/\*([^\n])/*\n$1/; 

print "$string\n"; 

Sortie:

* 
* 
* 
ab***c
Questions connexes