开发者

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 exp开发者_开发问答ression #1, char 7: unterminated s' command


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).


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.


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.

  1. The first two \\ is changed into \. Because the first \ is followed by the second \.
  2. 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 /.


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"


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..


I guess, you assuming \\\n or \\\t as three backslashes there, but actually, its 2 backslashes and another patterns

   backslash          \\
   newline            \n
   tab                \t

also, / might need to escape because in s/.../, / is using for open and close parts.

so /\\\/\// would be \\ + \/ + \/ according to your updated example


Replacing one backslash with two on my Cygwin requires this expression:

sed -e "s|\\|\\\\|g"

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜