Try this out for size:
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;
That makes a list, @temp
, based on the "words" (approximately) in $ligne
. It makes another list, @numbers
, which is a list of the numbers you want to replace in the list, in the order you want them to replace things. Then it goes through @temp
, one-by-one, and if a given element is a number (i.e. matches the regex /^\W*\d\W*$/
, which means it has no word characters (so it's not "champs4") and has at least one number - this will match "25346)" in addition to "25346"), and then replace the numeric part with the first value from @numbers
. And now that I've tested it, I can assure you this actually works!
I believe a shorter implementation could be achieved with map
, but this will work well enough for you.
Advantages of this approach to your approach:
First, this solution is scalable. To replace more than eight numbers with your solution, you would need to write a new regex. To replace more than eight numbers with my solution, just add a few more entries to @numbers
. This code could be put into a subroutine that takes a string to change and a list of numbers to change, and you wouldn't have to worry about whether or not they passed the right number of numbers, or whether they have the right format.
Second, this is a bit easier to understand at cursory glance. Regexes as long as the one you were using are very hard to parse visually. Even if it works, someday someone may need to alter your code to do something different. If you use a huge regex, the rewriter (perhaps you) will simply shake their heads, highlight your code, and press delete, and then write new code to do it. With this, they can easily see what is happening in your code, and if they need to make modifications to it, they can.
Third, if you want to hardcode in a specified number of replacements to make, you can do that too:
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;
As a side note (which applied earlier, but still applies), this will fail on floating point numbers - /^\W*\d\W*$/
will match floating point numbers, but s/\d+/$num/
won't replace floating point numbers, only the integer part. If you discover you need floating point numbers, change this line:
s/\d+/$num/;
To this:
s/\d+|(?:\d+)?\.\d+/$num/;
That should match floating point numbers.