Strange Behaviour of `bash` with echo statements
Environment
- Red Hat Enterprise Linux (RHEL) 5.8
bash
Issue
- On Red Hat Enterprise Linux 5.8, following commands are executed.
# export temp_tag_value=`echo "[2405:201:fffb:8a::4]" | sed 's/\//\\\\\//g'`
# echo $temp_tag_value
- On one of the servers, it works fine, but on other server it returns a vague value as 'a' or '1'.
- It seems that the command
echo $temp_tag_value
returns name of a file nameda
or1
which is present in the same directory, and if that file is removed, then it returns the expected output. - Why
bash
is behaving strangely?
Resolution
- This is expected behaviour. variables supplied as command parameters without quotes are subject to shell expansions including the pathname expansion. In order to prevent pathname expansion, embrace the variable with "" (double quotes).
- From
man bash
EXPANSION
Expansion is performed on the command line after it has been split into
words. There are seven kinds of expansion performed: brace expansion,
tilde expansion, parameter and variable expansion, command substitu-
tion, arithmetic expansion, word splitting, and pathname expansion.
The order of expansions is: brace expansion, tilde expansion, parame-
ter, variable and arithmetic expansion and command substitution (done
in a left-to-right fashion), word splitting, and pathname expansion.
- So the string "[2405:201:fffb:8a::4]" is expanded to file-names consisting of exactly one character from the [012458afb:] set in case there are such files present in current working directory. If there's no such named file in current directory, the original string is kept unexpanded.
- To prevent value of
$temp_tag_value
variable to be subject of pathname expansion, use
# echo "$temp_tag_value"
instead of
# echo $temp_tag_value
Root Cause
- This is expected behaviour - shell pathname expansion feature. This feature applies not only to
bash
but to other shells, such asksh
as well.
Diagnostic Steps
To Reproduce:
- When export is done, the echo statement is taking
a
instead of[2405:201:fffb:8a::4]
, see below.
[root@localhost ~]# export temp_tag_value=`echo "[2405:201:fffb:8a::4]" | sed 's/\//\\\\\//g'`
[root@localhost ~]# echo $temp_tag_value
[2405:201:fffb:8a::4]
[root@localhost ~]# touch a
[root@localhost ~]# echo "[2405:201:fffb:8a::4]" | sed 's/\//\\\\\//g'
[2405:201:fffb:8a::4]
[root@localhost ~]# ls a
a
[root@localhost ~]# echo "[2405:201:fffb:8a::4]" | sed 's/\//\\\\\//g'
[2405:201:fffb:8a::4]
[root@localhost ~]# export new="echo "[2405:201:fffb:8a::4]" | sed 's/\//\\\\\//g'"
[root@localhost ~]# echo $new
echo a | sed 's/\//\\\//g' <======== see here, [2405:201:fffb:8a::4] is replaced by a here.
- If we remove
a
, and createb
, then it will displayb
.
[root@localhost ~]# rm -rf a
[root@localhost ~]# touch b
[root@localhost ~]# export temp_tag_value=`echo "[2405:201:fffb:8a::4]" | sed 's/\//\\\\\//g'`
[root@localhost ~]# echo $temp_tag_value
b
[root@localhost ~]# touch c
[root@localhost ~]# export temp_tag_value=`echo "[2405:201:fffb:8a::4]" | sed 's/\//\\\\\//g'`
[root@localhost ~]# echo $temp_tag_value
b <<<<<<<<<==== output is b because in [2405:201:fffb:8a::4] there is no c character, there is only a, b and f available.
[root@localhost ~]# rm b
rm: remove regular empty file `b'? y
- Now try with
f
[root@localhost ~]# rm c
rm: remove regular empty file `c'? y
[root@localhost ~]# touch f
[root@localhost ~]# export temp_tag_value=`echo "[2405:201:fffb:8a::4]" | sed 's/\//\\\\\//g'`
[root@localhost ~]# echo $temp_tag_value
f
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.