Bash interpretation of quotes
Recently, I was attempting to pull a particular octet out of a list of IP addresses:
echo 192.168.0.1 | awk -F. '{ print $2 }'
168
That worked fine, but when I ran this through sh
, the result changed:
sh -c "echo 192.168.0.1 | awk -F. '{ print $2 }'" sh -c 'echo 192.168.0.1 | awk -F. "{ print $2 }"'
192.168.0.1 192.168.0.1
Thanks to a helpful post on Stackoverflow, it's clear that Bash is
doing something strange inside quotes. Specifically, anything inside
single quotes will be left alone, but characters inside double
quotes may not maintain their literal meaning. Above, since $2
is inside double quotes in both cases, it will be interpreted as a
Bash variable. Instead, we either need to escape the $
with a
backslash:
sh -c 'echo 192.168.0.1 | awk -F. "{ print \$2 }"' sh -c "echo 192.168.0.1 | awk -F. '{ print \$2 }'"
168 168
Or, we can keep everything inside single quotes. However, we can't just escape the ' with a backslash:
A single quote may not occur between single quotes, even when preceded by a backslash.
Hence, we have to:
- Close the single-quoted string (')
- Escape the single quote with a backslash (\')
- Re-open the single-quoted string and continue it (')
sh -c 'echo 192.168.0.1 | awk -F. '\''{ print $2 }'\'''
168