Escaping both forward slash and back slash with sed

I have the following string: /tmp/test/folder1/test.txt

I wish to use sed to substitute / for / – for example:

/tmp/test/folder1/test.txt

So I issue:

echo "/tmp/test/folder1/test.txt" | sed "s///\\//g"

Although it returns:

sed: -e expression #1, char 9: unknown option to `s’

I am escaping the forward slash and backslash – so not sure where I have gone wrong here

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You need to escape (with backslash ) all substituted slashes / and all backslashes separately, so:

$ echo "/tmp/test/folder1/test.txt" | sed 's///\//g'
/tmp/test/folder1/test.txt

but that’s rather unreadable.

However, sed allows to use almost any character as a separator instead of /, this is especially useful when one wants to substitute slash / itself, as in your case, so using for example semicolon ; as separator the command would become simpler:

echo "/tmp/test/folder1/test.txt" | sed 's;/;\/;g'

Other cases:

  • If one wants to stick with slash as a separator and use double quotes then all escaped backslashes have to be escaped one more time to preserve their literal values:
    echo "/tmp/test/folder1/test.txt" | sed "s///\\//g"
  • if one doesn’t want quotes at all then yet another backslash is needed:
    echo "/tmp/test/folder1/test.txt" | sed s/\//\\\//g

Method 2

Or, if the value is in a (bash) shell variable:

var=/tmp/test/folder1/test.txt
$ echo "${var////\/}"
/tmp/test/folder1/test.txt

The first // start parameter expansion, saying to replace all matches with the replacement. The next / is the escaped / to match, and the \/ is an escaped followed by an escaped / as the replacement.

Method 3

The final solution will be this one:

$ sed 's:/:\/:g'  <<<"$str"
/tmp/test/folder1/test.txt

But to explain how to get there:
Yes, you were missing one backslash:

$ str='/tmp/test/folder1/test.txt'
$ sed "s///\\//g" <<<"$str"
/tmp/test/folder1/test.txt

I hope that one space will make it clear:

$ sed "s///\\ //g"  <<<"$str"
 /tmp /test /folder1 /test.txt

But, if you were to change the sed delimiter to : (for example):

$  sed "s:/:\\/:g"  <<<"$str"
/tmp/test/folder1/test.txt

But that is not strictly correct as the (now not special) / does not need scaping:

$ sed "s:/:\\/:g"  <<<"$str"
/tmp/test/folder1/test.txt

And, if you were to use single quotes instead of double quotes the shell will not change double \ to one, so less will be correct:

$ sed 's:/:\/:g'  <<<"$str"
/tmp/test/folder1/test.txt

Which is quite cleaner.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x