Why does sed require 3 backslashes for a regular backslash?

后端 未结 7 1597
余生分开走
余生分开走 2020-11-29 01:26

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 compute

相关标签:
7条回答
  • 2020-11-29 01:54

    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.

    0 讨论(0)
  • 2020-11-29 01:54

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

    0 讨论(0)
  • 2020-11-29 02:03

    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

    0 讨论(0)
  • 2020-11-29 02:06

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

    0 讨论(0)
  • 2020-11-29 02:11

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

    0 讨论(0)
  • 2020-11-29 02:12

    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"
    
    0 讨论(0)
提交回复
热议问题