12

I'm trying to pad zero to a number

a=010
printf "%04d" $a
0008

I need the "output" as "0010" it's converting the value.

and even tried with typeset

a=010
typeset -RZ2 a
echo $a

when I use the same in my script I got the following error:

Invalid -R option
1
  • the problem in with the input, not the output. Aug 26, 2013 at 12:47

4 Answers 4

18

Don't put a "0" at the beginning of the number -- it treats the number in the octal base. Simply assign the decimal number.

a=10    
printf "%04d" $a    
0010    

If you are reading the numbers from somewhere else, you may consider removing the 0s at the beginning as follows:

a=0010    
b=$(echo $a | sed 's/^0*//')    
printf "%04d" $a    
0008
printf "%04d" $b    
0010    
3
  • b=$(echo $a | sed 's/^0*//')
    – user43067
    Aug 26, 2013 at 8:36
  • echo simply prints the value of the variable a, which is then redirected to sed (using the | character). Now, sed receives the string (i.e., value of a), and removes all the 0s at the beginning. The character ^ indicates beginning of a line; 0* means any number of zeroes including none. This essentially returns you the number with all 0s, if any, at the beginning removed. This value is then assigned to a new variable called b.
    – Barun
    Aug 26, 2013 at 9:17
  • Please, whipe useless pipe! Write b=$(sed s/^0*// <<<"$a") Mar 14, 2017 at 6:52
15

New answer using %08.0f

As %f is used to print decimal floating point, argument must be decimal.

So there is no risk to see argument interpreted as octal:

Do simply:

a=0010

a=`printf %08.0f $a` 

or

a=$(printf %08.0f $a)

then

echo $a
00000010

This work find under any POSIX

Under

Using , you could avoid fork by using -v option of printf:

a=0010
printf -v a %08.0f $a
echo $a
00000010

Old answer (using %d)

Under POSIX

You can drop the left 0 character with the following:

a=00010
while [ "$a" != "${a#0}" ] ;do a=${a#0};done
printf "%08d" $a
00000010

As this doesn't fork a new command session, this could be quicker than using sed.

Under

You can force decimal interpretation with the following syntax:

a=000010
printf "%08d" $((10#$a))
00000010

This could be useful for conversions:

a="0a"
printf "%04d" $((16#$a))
0010

a="00001010"
printf "%04d" $((2#$a))
0010

a="00012"
printf "%04d" $((8#$a))
0010

a="0020"
printf "%04d" $((5#$a))
0010

a="0013"
printf "%04d" $((7#$a))
0010

and so on...

a="zz"
printf "%04d" $((36#$a))
1295
2
  • b=$(echo $a | sed 's/^0*//') what exactly this step does ??
    – user43067
    Aug 26, 2013 at 8:37
  • 1
    @user43067 $() generate a new command session (fork), echo $a will run in this new session, than | sed will generate a new command session to pipe to /bin/sed outer binary. Aug 26, 2013 at 14:40
5

You can accomplish that by using a different conversion specifier, for example the "f" specifier. From the printf manual:

f, F

The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it.

But we don't really want a floating point representation of your number, so we must specify a precision of zero. This should do it:

a=010
printf "%04.0f" $a

I'm assuming you are using Linux, but this should also work with other flavours of Unix.

1
  • Or, from man printf, u could use: printf "%04g" 010! +1, interesting way to explore too... Aug 26, 2013 at 14:51
4

typeset -Z4 a will work with zsh or ksh.

When interpreted as a number, In POSIX sh and printf, if there's a leading zero, it's interpreted as an octal number. So, you need to strip those 0s first:

printf '%04d\n' "${a#"${a%%[!0]*}"}"

Or you could use awk that doesn't have that issue:

awk 'BEGIN{printf "%04d\n", ARGV[1]}' "$a"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .