Search code examples
bashshellawk

What causes `awk` to inject an extra '0' when embedding a shell variable incorrectly?


I have already seen this question and I now know how to pass shell variables correctly to awk.

However, I noticed a curious behavior in my initial incorrect attempts:

ip=10.170.115.13

echo $ip
10.170.115.13

echo foo | awk "{print ${ip} }"
10.170.1150.13

Observe the extra 0 in the output above.

Is this undefined behavior, or is there a logical reason why the 0 appears where it does?

Here is my awk version:

awk --version
awk version 20200816

This also happens with gawk:

gawk --version
GNU Awk 5.3.1, API 4.0, (GNU MPFR 4.2.1, GNU MP 6.3.0)
Copyright (C) 1989, 1991-2024 Free Software Foundation.

Solution

  • When the variable is substituted into the script, it looks like

    awk "{print 10.170.115.13 }"
    

    Since there are no quotes around the IP, awk tries to parse it as numbers, not a string.

    I think it's actually being parsed as 3 numbers: 10.170, .115, and .13. The extra 0 comes from the default format for printing floating point numbers, which always includes a digit before the decimal point; .13 gets printed as 0.13. .115 also becomes 0.115, but we don't get an extra zero there because 10.170 becomes 10.17 (since trailing zeroes after the decimal are discarded).

    The right solution is to use the -v option to convert the shell variable to an awk variable. To fix it with your variable substitution method you need to add literal quotes so it will be parsed as a string.

    awk "{print \"$ip\" }"