4

I am learning bash and trying to understand the different ways of making a substitution and assigning it to a variable.

Specifically, I'm changing Unix slashes ('/') to Windows ('\').

References:

With thanks to Seth and terdon.


Updated version. Original at bottom.

#!/bin/bash
origPath="/home/django_auth_lifecycle/urls.py"

path=$origPath
path=${path//\//\\}                      #Works
echo "Via bash (2-slash, no-g): $path"

path=$origPath
path=${path//\//\\}                      #Works
echo "Via bash (no dollar): $path"

path=$origPath
echo "${path}" | sed -e 's/\//\\/g'     #Works, but don't know how to assign to var
#echo "Via sed (slash, quotes): $path"

path=$origPath
path=$(echo "$path" | sed s/'\/'/'\\'/g)   #Works
echo "Via sed (slash, quotes): $path"

path=$origPath
path=$(echo $path | sed s:'\/':'\\':g)   #Works
echo "Via sed (colon, quotes): $path"

path=$origPath                           #This and all following are
path=sed 's:/:\\:g' <<<$path             #s:/:\\:g: No such file or directory
echo "Via sed/<<< (colon): $path"

path=$origPath
path=sed 's/\//\\:g' <<<$path
echo "Via sed/<<< (slash): $path"

path=$origPath
path=sed 's/"\/"/"\\":g' <<<$path
echo "Via sed/<<< (slash, quotes): $path"

Output:

$ bash ./initial_script3.sh
Via bash (2-slash, no-g): \home\django_auth_lifecycle\urls.py
Via bash (no dollar): \home\django_auth_lifecycle\urls.py
./initial_script3.sh: line 13: ${echo "${path}" | sed -e 's/\//\\/g'}: bad substitution
Via sed (slash, quotes): /home/django_auth_lifecycle/urls.py
Via sed (slash, quotes): \home\django_auth_lifecycle\urls.py
Via sed (colon, quotes): \home\django_auth_lifecycle\urls.py
./initial_script3.sh: line 25: s:/:\\:g: No such file or directory
Via sed/<<< (colon): /home/django_auth_lifecycle/urls.py
./initial_script3.sh: line 29: s/\//\\:g: No such file or directory
Via sed/<<< (slash): /home/django_auth_lifecycle/urls.py
./initial_script3.sh: line 33: s/"\/"/"\\":g: No such file or directory
Via sed/<<< (slash, quotes): /home/django_auth_lifecycle/urls.py

Output with debugging:

$ bash -x ./initial_script3.sh
+ origPath=/home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ path='\home\django_auth_lifecycle\urls.py'
+ echo 'Via bash (2-slash, no-g): \home\django_auth_lifecycle\urls.py'
Via bash (2-slash, no-g): \home\django_auth_lifecycle\urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ path='\home\django_auth_lifecycle\urls.py'
+ echo 'Via bash (no dollar): \home\django_auth_lifecycle\urls.py'
Via bash (no dollar): \home\django_auth_lifecycle\urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ sed -e 's/\//\\/g'
+ echo /home/django_auth_lifecycle/urls.py
\home\django_auth_lifecycle\urls.py
+ path=/home/django_auth_lifecycle/urls.py
++ sed 's/\//\\/g'
++ echo /home/django_auth_lifecycle/urls.py
+ path='\home\django_auth_lifecycle\urls.py'
+ echo 'Via sed (slash, quotes): \home\django_auth_lifecycle\urls.py'
Via sed (slash, quotes): \home\django_auth_lifecycle\urls.py
+ path=/home/django_auth_lifecycle/urls.py
++ sed 's:\/:\\:g'
++ echo /home/django_auth_lifecycle/urls.py
+ path='\home\django_auth_lifecycle\urls.py'
+ echo 'Via sed (colon, quotes): \home\django_auth_lifecycle\urls.py'
Via sed (colon, quotes): \home\django_auth_lifecycle\urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ path=sed
+ 's:/:\\:g'
./initial_script3.sh: line 25: s:/:\\:g: No such file or directory
+ echo 'Via sed/<<< (colon): /home/django_auth_lifecycle/urls.py'
Via sed/<<< (colon): /home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ path=sed
+ 's/\//\\:g'
./initial_script3.sh: line 29: s/\//\\:g: No such file or directory
+ echo 'Via sed/<<< (slash): /home/django_auth_lifecycle/urls.py'
Via sed/<<< (slash): /home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ path=sed
+ 's/"\/"/"\\":g'
./initial_script3.sh: line 33: s/"\/"/"\\":g: No such file or directory
+ echo 'Via sed/<<< (slash, quotes): /home/django_auth_lifecycle/urls.py'
Via sed/<<< (slash, quotes): /home/django_auth_lifecycle/urls.py

Original

Below is what I've tried. Unfortunately, I can only get one method to work (sed with a pipe and quoting each element). The first one was working, I swear, and now it's not.

What am I doing wrong?


#!/bin/bash
origPath="/home/django_auth_lifecycle/urls.py"

path=$origPath
path=${$path/\//\\/g}                    #WAS working, now not
echo "Via bash: $path"                   # ${$path/\//\\/g}: bad substitution

path=$origPath
path=${path/\//\\/g}                     #Bad output:
echo "Via bash (no dollar): $path"       #'\/ghome/django_auth_lifecycle/urls.py'

path=$origPath
path=$(echo $path | sed s/'\/'/'\\'/g)   #Works
echo "Via sed (slash, quotes): $path"

path=$origPath
#path=$(echo $path | sed s/\//\\/g)      #No error, but output=input
echo "Via sed (slash): $path"

path=$origPath
path=$(echo $path | sed s:'\/':'\\':g)   #Works
echo "Via sed (colon, quotes): $path"

path=$origPath
path=$(echo $path | sed s:\/:\\:g)       #sed: -e expression #1, char 7:
echo "Via sed (colon): $path"            #     unterminated `s' command

path=$origPath                           #This and all following are
path=sed 's:/:\\:g' <<<$path             #s:/:\\:g: No such file or directory
echo "Via sed/<<< (colon): $path"

path=$origPath
path=sed 's/\//\\:g' <<<$path
echo "Via sed/<<< (slash): $path"

path=$origPath
path=sed 's/"\/"/"\\":g' <<<$path
echo "Via sed/<<< (slash, quotes): $path"

Output:

$ bash ./initial_script3.sh
./initial_script3.sh: line 5: ${$path/\//\\/g}: bad substitution
Via bash: /home/django_auth_lifecycle/urls.py
Direct echo: \/ghome/django_auth_lifecycle/urls.py
Via bash (no dollar): \/ghome/django_auth_lifecycle/urls.py
./initial_script3.sh: line 14: \/ghome/django_auth_lifecycle/urls.py: No such file or directory
Via echo bash (no dollar): /home/django_auth_lifecycle/urls.py
Via sed (slash, quotes): \home\django_auth_lifecycle\urls.py
Via sed (slash): /home/django_auth_lifecycle/urls.py
Via sed (colon, quotes): \home\django_auth_lifecycle\urls.py
sed: -e expression #1, char 7: unterminated `s' command
Via sed (colon):
./initial_script3.sh: line 34: s:/:\\:g: No such file or directory
Via sed/<<< (colon): /home/django_auth_lifecycle/urls.py
./initial_script3.sh: line 38: s/\//\\:g: No such file or directory
Via sed/<<< (slash): /home/django_auth_lifecycle/urls.py
./initial_script3.sh: line 42: s/"\/"/"\\":g: No such file or directory
Via sed/<<< (slash, quotes): /home/django_auth_lifecycle/urls.py

Output with debugging:

$ bash -x ./initial_script3.sh
+ origPath=/home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
./initial_script3.sh: line 5: ${$path/\//\\/g}: bad substitution
+ echo 'Via bash: /home/django_auth_lifecycle/urls.py'
Via bash: /home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ echo 'Direct echo: \/ghome/django_auth_lifecycle/urls.py'
Direct echo: \/ghome/django_auth_lifecycle/urls.py
+ path='\/ghome/django_auth_lifecycle/urls.py'
+ echo 'Via bash (no dollar): \/ghome/django_auth_lifecycle/urls.py'
Via bash (no dollar): \/ghome/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ path=echo
+ '\/ghome/django_auth_lifecycle/urls.py'
./initial_script3.sh: line 14: \/ghome/django_auth_lifecycle/urls.py: No such file or directory
+ echo 'Via echo bash (no dollar): /home/django_auth_lifecycle/urls.py'
Via echo bash (no dollar): /home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
++ sed 's/\//\\/g'
++ echo /home/django_auth_lifecycle/urls.py
+ path='\home\django_auth_lifecycle\urls.py'
+ echo 'Via sed (slash, quotes): \home\django_auth_lifecycle\urls.py'
Via sed (slash, quotes): \home\django_auth_lifecycle\urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ echo 'Via sed (slash): /home/django_auth_lifecycle/urls.py'
Via sed (slash): /home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
++ sed 's:\/:\\:g'
++ echo /home/django_auth_lifecycle/urls.py
+ path='\home\django_auth_lifecycle\urls.py'
+ echo 'Via sed (colon, quotes): \home\django_auth_lifecycle\urls.py'
Via sed (colon, quotes): \home\django_auth_lifecycle\urls.py
+ path=/home/django_auth_lifecycle/urls.py
++ sed 's:/:\:g'
sed: -e expression #1, char 7: unterminated `s' command
++ echo /home/django_auth_lifecycle/urls.py
+ path=
+ echo 'Via sed (colon): '
Via sed (colon):
+ path=/home/django_auth_lifecycle/urls.py
+ path=sed
+ 's:/:\\:g'
./initial_script3.sh: line 34: s:/:\\:g: No such file or directory
+ echo 'Via sed/<<< (colon): /home/django_auth_lifecycle/urls.py'
Via sed/<<< (colon): /home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ path=sed
+ 's/\//\\:g'
./initial_script3.sh: line 38: s/\//\\:g: No such file or directory
+ echo 'Via sed/<<< (slash): /home/django_auth_lifecycle/urls.py'
Via sed/<<< (slash): /home/django_auth_lifecycle/urls.py
+ path=/home/django_auth_lifecycle/urls.py
+ path=sed
+ 's/"\/"/"\\":g'
./initial_script3.sh: line 42: s/"\/"/"\\":g: No such file or directory
+ echo 'Via sed/<<< (slash, quotes): /home/django_auth_lifecycle/urls.py'
Via sed/<<< (slash, quotes): /home/django_auth_lifecycle/urls.py
  • 2
    echo ${origPath//\//\\} – Cyrus Jan 9 '15 at 20:40
  • @Cyrus Updated my script with that near the top. It gives incorrect output. :( – aliteralmind Jan 9 '15 at 21:03
  • 3
    @aliteralmind, note carefully there are 2 leading / and no trailing /g: echo "${origPath//\//\\}". // to replace all, \/ to search for a slash (escaped to not clash with ->), / to separate the search and replace test, \\ to substitute a backslash. See gnu.org/software/bash/manual/… – glenn jackman Jan 9 '15 at 21:30
  • //\//\\ != /\//\\/g – Cyrus Jan 9 '15 at 21:30
  • With sed: echo "${origPath}" | sed -e 's/\//\\/g' – Cyrus Jan 9 '15 at 21:36
7

With "Parameter Expansion":

origPath="/home/django_auth_lifecycle/urls.py"
path="${origPath//\//\\}"
echo $path

Output:

\home\django_auth_lifecycle\urls.py


With a pipe, sed and "Command Substitution":

origPath="/home/django_auth_lifecycle/urls.py"
path="$(echo "${origPath}" | sed -e 's/\//\\/g')"
echo $path

Output:

\home\django_auth_lifecycle\urls.py


With sed, "Here String" and "Command Substitution":

origPath="/home/django_auth_lifecycle/urls.py"
path="$(sed -e 's/\//\\/g' <<< "${origPath}")"
echo $path

Output:

\home\django_auth_lifecycle\urls.py
  • Excellent. Thank you. Learned a lot today. One more question: Can you show how to use alternative delimiters with the parameter expansion version? (Like path="${origPath::\/:\\}". – aliteralmind Jan 9 '15 at 23:17
  • This is not possible. Parameter expansion has no alternative delimiters for search and replace like sed. If you use two : then you can make "Substring Expansion" like this: a="highway"; echo "${a:4:5}". Output: way – Cyrus Jan 9 '15 at 23:28
  • I wrote about this on my blog: aliteralmind.wordpress.com/2015/01/10/bashcrash – aliteralmind Jan 10 '15 at 6:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.