Essayez ceci pour la taille:
my @numbers = ($moyLargRectNom, $moyHautRectNom, $moyLargRectNom, $moyHautRectNom, $moyLargRectMat, $moyHautRectMat, $moyLargRectMat, $moyHautRectMat);
my @temp = split//, $ligne;
for(@temp) {
if(/^\W*\d\W*$/) {
my $num = shift @numbers;
s/\d+/$num/;
}
}
$ligne = join " ", @temp;
Cela fait une liste, @temp
, sur la base des "mots" (environ) à $ligne
. Il fait une autre liste, @numbers
, qui est une liste des numéros que vous voulez remplacer dans la liste, dans l'ordre où vous voulez qu'ils remplacent les choses. Ensuite, il passe par @temp
, un par un, et si un élément donné est un nombre (ie correspond à la regex /^\W*\d\W*$/
, ce qui signifie qu'il n'a pas de caractères de mot (donc ce n'est pas "champs4") et a au moins un nombre - ceci correspondra à "25346)" en plus de "25346"), puis remplacez la partie numérique par la première valeur de @numbers
. Et maintenant que je l'ai testé, je peux vous assurer que cela fonctionne réellement!
Je crois qu'une implémentation plus courte pourrait être réalisée avec map
, mais cela fonctionnera assez bien pour vous.
Les avantages de cette approche à votre approche:
En premier lieu, cette solution est évolutive. Pour remplacer plus de huit numéros avec votre solution, vous devez écrire une nouvelle expression rationnelle. Pour remplacer plus de huit nombres avec ma solution, ajoutez juste quelques autres entrées à @numbers
. Ce code pourrait être mis dans un sous-programme qui prend une chaîne à changer et une liste de nombres à changer, et vous n'aurez pas à vous soucier de savoir s'ils ont passé le bon nombre de nombres ou s'ils ont le bon format. Deuxièmement, c'est un peu plus facile à comprendre au premier coup d'œil. Les expressions régulières, aussi longues que celle que vous utilisiez, sont très difficiles à analyser visuellement. Même si cela fonctionne, un jour quelqu'un peut avoir besoin de modifier votre code pour faire quelque chose de différent. Si vous utilisez une regex énorme, le réécriteur (peut-être vous) va simplement secouer la tête, mettre en évidence votre code, et appuyez sur supprimer, puis écrire un nouveau code pour le faire. Avec cela, ils peuvent facilement voir ce qui se passe dans votre code, et s'ils ont besoin d'y apporter des modifications, ils peuvent le faire.
Troisièmement, si vous voulez hardcode dans un certain nombre de remplacements à faire, vous pouvez le faire aussi:
my @numbers = ($moyLargRectNom, $moyHautRectNom, $moyLargRectNom, $moyHautRectNom, $moyLargRectMat, $moyHautRectMat, $moyLargRectMat, $moyHautRectMat);
my @temp = split//, $ligne;
my $max_replacements = 8;
for(@temp) {
if(/^\W*\d\W*$/) {
my $num = shift @numbers;
s/\d+/$num/;
last unless --$max_replacements;
}
}
$ligne = join " ", @temp;
Comme une note latérale (qui appliqué plus tôt, mais applique encore), cela ne fonctionne pas sur les nombres à virgule flottante - /^\W*\d\W*$/
correspondra aux nombres à virgule flottante, mais s/\d+/$num/
ne remplacera pas les nombres à virgule flottante, seulement la partie entière.Si vous découvrez que vous avez besoin nombres à virgule flottante, changez cette ligne:
s/\d+/$num/;
à ceci:
s/\d+|(?:\d+)?\.\d+/$num/;
Cela doit correspondre à un nombre à virgule flottante.
Note: Vous avez seulement 5 groupes parenthésées dans votre modèle, mais vous utilisez des backreferences 6 $ pour 9 $. Pourquoi? –
Je ne peux pas reproduire votre problème: Même avec les backreferences supplémentaires, la substitution fonctionne pour moi. Recevez-vous des messages d'erreur ou d'avertissement? –
Salut Nathan, j'ai 8 valeurs à remplacer dans la chaîne. – user105265