[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#10782: zero padding does not work in case of strings

From: Eric Blake
Subject: bug#10782: zero padding does not work in case of strings
Date: Fri, 10 Feb 2012 12:29:53 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20120131 Thunderbird/10.0

tag 10782 notabug

On 02/10/2012 11:52 AM, Praveen A wrote:
> $ printf %04d 12
> 0012$ printf %4d 12
>   12$ printf %04s 12
>   12$ printf %4s 12
>   12$

Thanks for the report.  In printf(3), POSIX states the use of the 0
modifier with %s is undefined:


"0    For d , i , o , u , x , X , a , A , e , E , f , F , g , and G
conversion specifiers.... For other conversions, the behavior is undefined."

Note that glibc silently ignores %04x, and gcc correctly warns about it
being fishy:

$ cat foo.c
#include <stdio.h>
int main() { printf("%04s\n", "hi"); return 0; }
$ gcc -o foo foo.c -Wall
foo.c: In function ‘main’:
foo.c:2:1: warning: '0' flag used with ‘%s’ gnu_printf format [-Wformat]
$ ./foo

> It would be very useful if it works for strings too (I found this when
> trying to zero pad hex values in an ipv6 address). Now it requires an
> additional sed find and replace to get the desired result.

Note that you didn't even test coreutils - you tested the built-in
printf of your shell.  Coreutils intentionally errors out on this
undefined behavior, to make it obvious that there is no sane documented
way to implement it:

$ /usr/bin/printf %04s 12
/usr/bin/printf: %04s: invalid conversion specification

Implementing %04s in coreutils, but not also in glibc, bash, dash, ksh,
and so forth, all at the same time, would just cause user confusion due
to the inconsistencies; plus, you would have to wait for those fixes to
propagate into your machine before you could rely on it.  Rather, you
should patch your script to use %d or %x or other tricks in a manner
that works today:

# Use $(()) to convert hex to decimal, then 0-pad it back out to hex
$ printf %04x $((0x12))

# given an arbitrary string in $1, add 0-padding if needed to extend
# it to at least 4 characters
$ f() {
  case ${#1} in
    0|1|2|3) printf %0$((4-${#1}))d%s 0 "$1" ;;
    *) printf %s "$1" ;;
$ f 12

As such, I'm closing this bug report as something we won't change.

Eric Blake   address@hidden    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature

reply via email to

[Prev in Thread] Current Thread [Next in Thread]