I came across some strangely inconsistent behavior in BASH parameter expansions across a few different servers, while trying to write a quick function.
On some versions of BASH, to use a tilde in a substring replacement, the tilde must be escaped, or it will be re-expanded to the home directory:
foo=~/data # ~ is expanded to $HOME bar1="${foo/#$HOME/~}" # returns ~/data bar2="${foo/#$HOME/"~"}" # returns ~/data bar3="${foo/#$HOME/~}" # returns /home/user/data
while on other systems, it will not be re-expanded, and attempting to escape the tilde will add the literal escape characters to the string:
foo=~/data # ~ is expanded to $HOME bar1="${foo/#$HOME/~}" # returns ~/data bar2="${foo/#$HOME/"~"}" # returns "~"/data bar3="${foo/#$HOME/~}" # returns ~/data
Note my goal here is to insert the literal string “~”.
The BASH versions where no escape was necessary are here:
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0) Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> GNU bash, version 4.2.37(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
The BASH version where an escape was necessary is here:
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
So what is going on?
Advertisement
Answer
@iBug posted how to ensure we always expand the tilde. To ensure we always get the tilde character itself on any system, use this:
bar="${foo/#$HOME/~}" # returns ~/data or /home/user/data [[ "$bar" =~ "$HOME"* ]] && bar="${foo/#$HOME/~}"
which redoes the substitution with escaped tilde only if the original non-escaped tilde was expanded.