Skip to content

Instantly share code, notes, and snippets.

@msamendinger
Last active July 10, 2024 00:19
Show Gist options
  • Save msamendinger/c2da6f5fafc43e72ef576a0cc7ad0165 to your computer and use it in GitHub Desktop.
Save msamendinger/c2da6f5fafc43e72ef576a0cc7ad0165 to your computer and use it in GitHub Desktop.
# what happens when we want to replace a string with a variable with a forward slash in its value?
$ var1="test/string"
$ echo "this is a test" | sed "s/test/$var1/"
sed: 1: "s/test/test/string/g": bad flag in substitute command: 's'
# set has delimiter confusion let's use another delimiter
$ echo "this is a test" | sed "s#test#$var1#"
this is a test/string
# works but what if we want to use #s
$ var2="test/string # comment"
$ echo "this is a test" | sed "s#test#$var2#"
sed: 1: "s#test#test/string # co ...": bad flag in substitute command: 'c'
# again delimiter confusion
# We have to escape the forward slash with \ should be easy with sed... wait :thinking:
# as we're already fighting with sed let's use bash parameter expansion
$ echo "this is a test" | sed "s/test/${var2/\//\\/}/" # replace / with \/
this is a test/string # comment
# what about two forward slashes?
$ var3="test//string # comment"
$ echo "this is a test" | sed "s/test/${var3/\//\\/}/"
sed: 1: "s/test/test\//string # ...": bad flag in substitute command: 's'
# what happened?
$ echo ${var3/\//\\/}
test\//string # comment
# only one forward slash got replaced
# we begin our parameter expansion with a forward slash to replace all matches
# makes it even easier to read, right?
$ echo "this is a test" | sed "s/test/${var3//\//\\/}/"
this is a test//string # comment
# great, now that we have that working lets use
$ var4="test//string # comment about using \ backslash"
$ echo "this is a test" | sed "s/test/${var4//\//\\/}/"
this is a test//string # comment about using backslash
# we're missing the backslash. Ok back to work, we have to escape the backslash
# bash parameter expansion does not allow multiple substitutions so back to sed
# in a first step let's escape the forward slashes only, we use /g to replace
# all matches
# we escape every / as \/ and every \ as \\
$ var5=$(sed "s/\//\\\//g" <<< $var4)
sed: 1: "s/\//\\//g": bad flag in substitute command: '/'
# what? if something is not working just add more backslashes...
# escape all escape characters.
$ var5=$(sed "s/\//\\\\\//g" <<< $var4)
$ echo $var5
test\/\/string # comment about using \ backslash
$ echo "this is a test" | sed "s/test/$var5/"
this is a test//string # comment about using backslash
# this is fine as the backslash did get no love yet.
# but now that we know we have to use 4 backslashes to match 1 its easy
$ var5=$(sed "s/\\\\/\\\\\\\\/g; s/\//\\\\\//g;" <<< $var4)
$ echo "this is a test" | sed "s/test/$var5/"
this is a test//string # comment about using \ backslash
@fluktegrute
Copy link

Hi,
I came accross here after I had to replace with a string containing slashes... Just to let you know, you can actually use any single byte character as a separator in sed.
sed -i "s|$match|$replace|" file

@msamendinger
Copy link
Author

Oh I missed your comment. You're right arbitrary single byte characters can be used. On line 6 I used a hash as delimiter. The text I wanted to replace was not known before and unstructured so I wasn't sure what character I can safely use.
With single quotes the situation would have also improved
var5=$(sed 's/\\/\\\\/g; s/\//\\\//g;' <<< $var4)

At the end this shouldn't be taken too serious ;)

@4riful
Copy link

4riful commented Aug 28, 2022

can't thank you enough man it saved my live

@4riful
Copy link

4riful commented Aug 28, 2022

btw
match="a="somethinng""
replace="b="somme/some""
how to escape " and / here with sed ??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment