I have some simple data with leading zeros, and I want to interpolate some additional values. Something like this:
$ printf "C011=4\nC015=8\n" | perl -ne '/C(\d\d\d)=(.*)/; $l{$1}=$2 }{ $l{13}=($l{15}-$l{11})/2+$l{11}; printf "C%03d=%f\n",$_,$l{$_} for keys %l;'
C011=4.000000
C013=0.000000
C015=8.000000
Okay. Perl's not matching 11
to 011
In the simple case above, you might think, hey, whatever, let's use the leading zeros in the hash keys for the arithmetic:
$ printf "C011=4\nC015=8\n" | perl -ne '/C(\d\d\d)=(.*)/; $l{$1}=$2 }{ $l{013}=($l{015}-$l{011})/2+$l{011}; printf "C%03d=%f\n",$_,$l{$_} for keys %l;'
C011=4.000000
C011=0.000000
C015=8.000000
Here I apparently have as keys the string 011 which printf
turns into 11, and the octal number 013, which printf turns into 11. And the lookup of the 011
and 015
values still failed.
What are the options in perl for avoiding the behavior of numbers with leading zeros (and no 9's) being interpreted as octal? I want the hash keys to have their appropriate decimal value.
I have a workaround. I just want to see if it's the most succinct solution. Something like a global don't-do-this, I'm never using octals.
Expected output:
C011=4.000000
C013=6.000000
C015=8.000000
The problem with the original code is that hash keys are strings, and 011
and 11
are different strings.
Solution 1: Use the correct string.
perl -ne'
/C(\d\d\d)=(.*)/; $l{$1}=$2;
END {
$l{"013"}=($l{"015"}-$l{"011"})/2+$l{"011"};
printf "C%s=%f\n",$_,$l{$_} for sort keys %l;
}
'
It's simpler to include the C
.
perl -ne'
/(C\d\d\d)=(.*)/; $l{$1}=$2;
END {
$l{C013}=($l{C015}-$l{C011})/2+$l{C011};
printf "%s=%f\n",$_,$l{$_} for sort keys %l;'
}
'
Solution 2: Convert the captured strings to match those produced by the code.
Replace $l{$1}=$2
with $l{0+$1}=$2
.
This will numify 011
to eleven, then stringify that to 11
.
This supports any number of leading zeros.