awk output discrepancy

I noticed a discrepancy while running AWK on different platforms/versions:

SunOS

$ echo "78" | awk '{ printf "%c\n", $0 }'
N
$ awk 'BEGIN{ printf "%c\n", "78" }' /dev/null
N

Linux / HP-UX

$ echo "78" | awk '{ printf "%c\n", $0 }'
N
$ awk 'BEGIN{ printf "%c\n", "78" }' /dev/null
7

Can somebody explain why the output is 7 instead of N?

Hi Yoda, it is numerical versus string input for the printf command. Compare:

awk 'BEGIN{ printf "%c\n", "78" }' 

to

awk 'BEGIN{ printf "%c\n", 78 }'

or

echo "78" | awk '{ printf "%c\n", $0 }'

vs.

echo "78" | awk '{ printf "%c\n", $0"" }'
1 Like

I'd expect 7, since it's a string in that case. It seems it has to do with when it's converted between a string and int. I've several awk implementations installed locally, oawk is from heirloom tools which should be close to SunOS's.

$ try() { for awk in gawk mawk oawk bawk; do printf '%s: ' "$awk"; $awk "$@"; done; }
$ try 'BEGIN{ printf "%c\n", "78" }' /dev/null
gawk: 7
mawk: 7
oawk: N
bawk: 7

So what's oawk doing? Well, looks like it's using it as an int ALL THE TIME. I haven't the oawk code around anymore to dig any deeper. Perhaps it has its own printf? I've only known %c to be useful for casting an int to char. But in that first bit, it is internally made an int, unless we tack a null string to it then we're back to getting 7's.

for awk in gawk mawk oawk bawk; do printf '%s: ' "$awk"; echo 78 | $awk '{ printf "%c\n", $0 "" }'; done;
gawk: 7
mawk: 7
oawk: N
bawk: 7
1 Like

Thanks Scrutinizer, that explains it!

I added a 0 to convert and it worked:

$ cat file
796f6461
awk '
        {
                for ( i = 1; i <= length($0); i += 2 )
                {
                        hex = sprintf ( "0x%s", substr ( $0, i, 2 ) )
                        dec = sprintf ( "%d", strtonum ( hex ) )
                        sym = sprintf ( "%c", dec )
                        s = s ? s sym : sym
                }
        }
        END {
                print s
        }
' file
1119
awk '
        {
                for ( i = 1; i <= length($0); i += 2 )
                {
                        hex = sprintf ( "0x%s", substr ( $0, i, 2 ) )
                        dec = sprintf ( "%d", strtonum ( hex ) )
                        dec = dec + 0
                        sym = sprintf ( "%c", dec )
                        s = s ? s sym : sym
                }
        }
        END {
                print s
        }
' file
yoda

oh I took the wrong approach with that answer. :stuck_out_tongue: