I need Perl's auto-increment magic for strings, but some strings (such as those composed entirely of digits) are interpreted as numbers and a normal increment is performed instead. How would I force Perl to treat a value passed to ++
as a string?
Asked
Active
Viewed 82 times
1

jaymmer - Reinstate Monica
- 4,238
- 4
- 28
- 34
-
Can you explain how you expect strings composed of entirely digits to increment? This may help: http://stackoverflow.com/questions/3508362/autoincrementing-letters-in-perl You might have to write your own "increment" function for this. – hmatt1 Mar 04 '15 at 02:51
-
I'd expect `++(my $v = "0001")` to become "0002" instead of just "2", for example. Of course, this isn't limited to just strings composed entirely of digits - after `++(my $a = "M2U0")`, for example, `$a` becomes `1` instead of `"M2U1"` which is what I want. – jaymmer - Reinstate Monica Mar 04 '15 at 02:59
-
`0001` should become `0002` but I don't think your other example would work. This is because for the variable to be incremented as a string, it has to 1. match the regex `/^[a-zA-Z]*[0-9]*\z/` and 2. only be used in string contexts. This was explained in the docs you linked to. – hmatt1 Mar 04 '15 at 03:04
-
1Just tested this, `perl -e'my $var = "0001"; $var++; print $var'` prints `0002`. So that part works. `perl -e'my $var = "M2U0"; $var++; print $var'` prints `1` because it doesn't match the regex and is being treated in numeric context. – hmatt1 Mar 04 '15 at 03:06
-
Hm, I just tried it as well and it works just fine for me as well, I must have messed something up. I didn't think to actually take a good look at the regular expression itself; it seems that the auto-increment magic won't do the job after all. – jaymmer - Reinstate Monica Mar 04 '15 at 03:08
1 Answers
2
Here's the related question about how auto incrementing works: Autoincrementing letters in Perl
Like the docs explained, basically you need the variable to
- match the regex
/^[a-zA-Z]*[0-9]*\z/
and - only be used in string contexts.
Because you have variables that don't match the regex, those ones will be treated as numbers. You can write your own increment function to get your desired functionality. Here's an idea I had about how it could work to get you started.
#!/usr/bin/perl
use strict;
use warnings;
my $test = "1000";
for (0..100) {
$test = increment($test);
}
print $test . "\n";
$test = "M2V3";
for (0..100) {
$test = increment($test);
}
print $test . "\n";
sub increment {
my ($str) = @_;
my @letters = reverse split //, $str;
my $add = "";
my $increment = 1;
my $result = "";
for my $let (@letters) {
if ( $increment == 1 ) {
++$let;
}
if ( $let =~ /(.)(.)/ ) {
$add = $2;
$increment = 1;
} else {
$add = $let;
$increment = 0;
}
$result = $add . $result;
}
return $result;
}
This outputs:
1101
M3F4
I didn't calculate to confirm that M3F4
is the correct result but it seems close.
-
I've always assumed there were easy to use functions in a `Util` module somewhere that could do fancy incrementation but never can find them. Thanks! [`String::Incremental`](https://metacpan.org/pod/String::Incremental) is pretty cool but seems a bit heavy-duty for what is seems (deceptively) like a simple problem. – G. Cito Mar 04 '15 at 15:54