1. Introduction

When scripting or formatting command arguments, we may want to transform numbers. One such transformation is the so-called zero padding. In essence, padding with zeroes results in a fixed-length number with as many zero prefixes or fractional suffixes as needed. For example, when padding to five (5) characters, 666 would become 00666, while 66600 would remain unchanged.

In this tutorial, we explore standard methods to pad a number with zeroes in the Linux shell. First, we use a shell built-in. Next, a tool available on the majority of Linux systems takes the spotlight. Finally, we discuss standardized ways to remove zero prefixes and suffixes.

Notably, although the same can be achieved with third-party tools such as interpreters like Perl and Python, we only explore solutions available in standard Linux environments and shells.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments.

2. Zero Padding With Bash printf

Since the name of the printf Bash builtin means print formatted, it’s the de facto way to format different data types for printing.

2.1. Integer

First, let’s output a regular decimal integer with the %d format specifier:

$ printf '%d' 666
666

Now, we can pad our number to eight characters:

$ printf '%08d' 666
00000666

By adding a 0 after the % percent sign, we request zero padding. The number (8) between 0 and the format specifier d designates the desired total number length.

2.2. Floating Point

In fact, we can perform padding with a floating point number as well:

$ printf '%010.5f' 666.0666
0666.06660

Let’s decode the format string:

  • % – format specifier start
  • 0 – zero padding
  • 10 – total result length (with decimal point)
  • . – fraction format specifier start
  • 5 – fraction length with postfix zero padding
  • f – floating point format

Notably, we get 10 characters in total, but one of them is the decimal point. Further, zero padding is postfixed for the fractional part.

2.3. Zero Prefixes

In fact, there is an important pitfall to zero padding when using printf:

$ printf '%d' 0666
438

Critically, prefixing the actual number with 0 beforehand would result in printf interpreting it as an octal. Later, we’ll explore ways to avoid such situations.

3. Zero Padding With awk

awk‘s built-in printf statement enables us to output data in the required format:

$ awk 'BEGIN { printf "%05d\n", "666" }'
00666

Of course, we can use shell variables in awk:

$ num=666
$ awk -v input="$num" 'BEGIN{ printf "%05d\n", input }'
00666

The format string of awk printf adheres to the same rules as that of Bash.

4. Removing Zero Padding

In general, there are several methods to remove zero padding and avoid issues with it when using printf.

In our examples, we either use a literal number or the one within the $num variable:

$ num=0666
$ echo "$num"
0666

Let’s see how we can remove the padding.

4.1. Loop

Initially, we can remove all 0 prefixes with a shell loop:

$ while [ "$num" != "${num#0}" ]; do num=${num#0}; done

If we know we have a floating point number, using ${num%0} with the same syntax would also remove 0 suffixes.

Even better, this method uses standard POSIX parameter expansion, so it’s highly portable.

4.2. Using awk

The standard awk utility provides at least four ways to remove zero-padding:

Let’s see the sub() regex awk solution first:

$ echo "0666" | awk '{sub(/^0*/,"")}1'
666

In this case, we match as many zeroes as possible with the * wildcard after 0 from the ^ beginning of the string. Next, we replace them with an “” empty string. After that, we use a print shortcut (1) after the } closing curly bracket.

Alternatively, for integers, we can simply do a conversion with int() and perform the same print:

$ echo "0666" | awk '{$0=int($0)}1'
666

When we perform arithmetic operations such as +, -, *, /, on a string, awk implicitly converts the string to a number. Therefore, we can make use of this feature to remove the leading zeros. Let’s see some examples:

$ awk '{$0=$0+0}1' <<< "0666" 
666

$ awk '{$0=$0*1}1' <<< "0666"
666

$ awk '{$0=$0-0}1' <<< "0666"
666

It’s worth mentioning that we used “here string” instead of “echo and pipe” in the examples above to provide input to awk. The advantage is we don’t need an extra process to feed awk input data.

Finally, we can employ the printf statement of awk just like printf in Bash:

$ awk '{printf "%08d\n",$0;}' <<< "0666"
00000666

Now, let’s use one more standard POSIX tool.

4.3. Using sed

Another way to remove 0 affixes uses sed:

$ echo "$num" | sed 's/^0*//'
666

Here, we employ a sed regular expression to match zero or more 0 characters at the ^ beginning of the string. Then, just like with awk, we [s]ubstitute them with an // empty string.

In the case of floating point number suffix padding, we can use a similar regular expression:

$ echo 6660.066600 | sed 's/0*$//'
6660.0666

This time, we remove relative to the $ end of the number string.

5. Summary

In this article, we looked at ways to add and remove zero padding in a standard POSIX environment.

In conclusion, many vanilla shells, including Bash, provide the necessary utilities for prepending, appending, and removing zeroes from numbers.