Why does sed require 3 backslashes for a regular backslash?
I'm curious, why does sed need 3 \
just to recognize one? I'd understand it needing 2, but 3 I don't.
EDIT: here's an example on my Windows computer, using Cygwin:
$ echo "sample_input\whatever" | sed "s/\\\/\//"
sample_input/whatever
If I don't add 3 backslashes, I get a
sed: -e expression #1, char 7: unterminated s' command
Solution 1:
I was able to reproduce this behavior using Vista and Cygwin 1.7.0.
- Two backslashes produce the error
- either three or four backslashes work
- Five gives the same error
Two backslashes become a single backslash in the shell which then in sed escapes the forward slash which is the middle delimiter.
\\/ -> \/ (which makes the forward slash a regular character instead of a delimiter)
Three of them: The first two become one in the shell which then escape the third one in sed
\\\/ -> \\/
Four: Each pair become single ones in the shell then the first resulting one escapes the second in sed
\\\\/ -> \\/
Edit:
Oh, I forgot to say that both single quotes and double quotes worked the same for me (cmd.exe
doesn't make the distinction that Bash, et al, makes).
Solution 2:
Your shell (probably bash) is doing its own escaping, and that's confusing you. You can use an echo command to see what is being passed, or it's easy to write a custom program (commonly named "showargs" or similar):
$ echo "s/\\\/\//" s/\\/\// $ echo "s/\\/\//" s/\/\//
You can also use single quotes, which are treated differently in bash.
Solution 3:
That's due to sh
's double-quoted string parsing rule.
Posix specifies how sh
parses double-quoted strings.
The backslash shall retain its special meaning as an escape character (see Escape Character (Backslash)) only when followed by one of the following characters when considered special: $ ` " \
In other words, sh
lefts the backslash which is followed by characters other than $ ' " .
So, if sh
meets the double-quoted string sed "s/\\\/\//"
, sh
parses it as follows.
- The first two
\\
is changed into\
. Because the first\
is followed by the second\
. - The third and fourth
\
is still left in the string. Because both of them are followed by/
, which is not special in double-quoted string.
After pasring, sh
passes the string s/\\/\//
to sed
, which substitutes the first occurence of \
into /
.
With same reasoning, when sh
meets the string, "sed s/\\\\/\//"
, sh
passes /\\/\//
to sed
, which also substitutes the first occurence of \
into /
.
Solution 4:
Please show an example of what you have in future. in sed, say you want to replace a "\
" with pipe (|), for example
$ cat file
asklfja \ asf
$ sed 's/\\/|/g' file
asklfja | asf
$ sed 's%\\%|%g' file #using different delimiter
asklfja | asf
you just need to escape it once.
Edit: To @OP's example, since you are using cmd.exe and not bash/ksh, cmd.exe doesn't like single quotes. I cannot produce your scenario. This works for my GNU sed on windows using 2 slashes
eg
C:\test>echo "sample_input\whatever" | sed "s/\\/\//"
"sample_input/whatever"
Solution 5:
In my version of CYGWIN, it works as the original poster says, but, works differently (normally) if I use single quotes.
$ echo "sample_input\whatever" | sed 's/\\/\//' sample_input/whatever
$ echo "sample_input\whatever" | sed "s/\\/\//" sed: -e expression #1, char 7: unterminated `s' command
Hmmm..