Can anybody explain this behaviour of the bash shell which is driving me nuts
[root@ns1 bin]# export test=`whois -h whois.lacnic.net 187.14.6.108 | grep -i inetnum: | awk '{print $2}'`
[root@ns1 bin]# echo $test
187.12/14
[root@ns1 bin]# echo "iptables -I INPUT -s $test -J DROP"
-J DROP -I INPUT -s 187.12/14
[root@ns1 bin]#
Why is my echo
screwed up? It is being changed by the contents of $test
.
If you change $test
to "ABC" all is fine. Is it related to the slash?
Why is my echo
screwed up? It is being changed by the contents of
$test
.
Because your test
contains a carriage return. Remove it:
test=$(whois -h whois.lacnic.net 187.14.6.108 | grep -i inetnum: | awk '{print $2}' | tr -d '\r')
Your test
contains something like
1234567 -I INPUT -s 187.12/14\r-J DROP
which, due to the carriage return, is visible only as
-J DROP -I INPUT -s 187.12/14
The CR moves the cursor to the start-of-line, where it then overwrites previous characters.
You could try
echo "$test" | od -bc
to verify this.
This is almost certainly a carriage return. echo
is doing its job correctly and emitting the string to your terminal; the problem is that your terminal is treating a part of the string as a command for it to follow (specifically, a LF character, $'\r'
, telling it to send the cursor to the beginning of the existing line).
If you want to see the contents of $test
in a way which doesn't allow your terminal to interpret escape sequences or other control characters, run the following (note that the %q
format string is a bash extension, not available in pure-POSIX systems):
printf '%q\n' "$test"
This will show you the precise contents formatted and escaped for use by the shell, which will be illuminative as to why they are problematic.
To remove $'\r'
, which is almost certainly the character giving you trouble, you can run the following parameter expansion:
test=${test//$'\r'/}
Unlike solutions requiring piping launching an extra process (such as tr
), this happens inside the already-running bash shell, and is thus more efficient.