perlradixoctalleading-zerotype-coercion

Best way to ensure decimal interpretation of string with leading zeros?


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

Solution

  • 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.