Por que o sed exige 3 barras invertidas para uma barra invertida regular?

Estou curioso, por que o sed precisa apenas reconhecer um? Eu entendo que precisa de 2, mas 3 eu não.

EDIT: aqui está um exemplo no meu computador com Windows, usando o Cygwin:

 echo "sample_input\whatever" | sed "s/\\\/\//" 

Se eu não adicionar 3 barras invertidas, recebo uma

 sed: -e expression #1, char 7: unterminated s' command 

Consegui reproduzir esse comportamento usando o Vista e o Cygwin 1.7.0.

  • Duas barras invertidas produzem o erro
  • três ou quatro barras invertidas funcionam
  • Cinco dá o mesmo erro

Duas barras invertidas se transformam em uma única barra invertida no shell, que depois, em sed, escapa da barra invertida que é o delimitador do meio.

 \\/ -> \/ (which makes the forward slash a regular character instead of a delimiter) 

Três deles: Os dois primeiros tornam-se um no shell que, em seguida, escaping do terceiro em sed

 \\\/ -> \\/ 

Quatro: Cada par se torna único no shell, então o primeiro resultante escapa do segundo em sed

 \\\\/ -> \\/ 

Editar:

Ah, esqueci de dizer que aspas duplas e aspas duplas funcionavam da mesma maneira para mim (o cmd.exe não faz a distinção que Bash, et al, faz).

Seu shell (provavelmente bash) está fazendo seu próprio escape, e isso está confundindo você. Você pode usar um comando echo para ver o que está sendo passado ou é fácil escrever um programa personalizado (comumente chamado de “showargs” ou similar):

 $ echo "s / \\\ / \ //"
 s / \\ / \ //
 $ echo "s / \\ / \ //"
 s / \ / \ //

Você também pode usar aspas simples, que são tratadas de maneira diferente no bash.

Isso é devido à regra de análise de strings de aspas duplas de sh .

Posix especifica como sh analisa strings com aspas duplas.

A barra invertida deve manter seu significado especial como um caractere de escape (consulte Escape Character (Backslash)) somente quando seguido por um dos seguintes caracteres quando considerado especial: $ `” \

Em outras palavras, sh deixa a barra invertida que é seguida por caracteres diferentes de $ ‘”.

Então, se sh encontra a string de aspas duplas sed "s/\\\/\//" , sh analisa da seguinte maneira.

  1. Os dois primeiros \\ são alterados em \ . Porque o primeiro \ é seguido pelo segundo \ .
  2. O terceiro e quarto \ ainda é deixado na string. Porque ambos são seguidos por / , o que não é especial na cadeia de aspas duplas.

Depois do pasring, sh passa a string s/\\/\// para sed , que substitui a primeira ocorrencia de \ into / .

Com o mesmo raciocínio, quando sh encontra a string, "sed s/\\\\/\//" , sh passa /\\/\// para sed , que também substitui a primeira ocorrência de \ into / .

Por favor, mostre um exemplo do que você tem no futuro. em sed, digamos que você quer replace um ” \ ” com pipe (|), por exemplo

 $ cat file asklfja \ asf $ sed 's/\\/|/g' file asklfja | asf $ sed 's%\\%|%g' file #using different delimiter asklfja | asf 

você só precisa escaping uma vez.

Edit: Para o exemplo do @ OP, uma vez que você está usando o cmd.exe e não o bash / ksh, o cmd.exe não gosta de aspas simples. Eu não posso produzir seu cenário. Isso funciona para o meu GNU sed no windows usando 2 barras

por exemplo

 C:\test>echo "sample_input\whatever" | sed "s/\\/\//" "sample_input/whatever" 

Na minha versão do CYGWIN, funciona como o pôster original diz, mas funciona de forma diferente (normalmente) se eu usar aspas simples.

 $ echo "sample_input \ whatever" |  sed 's / \\ / \ //'
 sample_input / whatever
 $ echo "sample_input \ whatever" |  sed "s / \\ / \ //"
 sed: -e expressão # 1, char 7: comando 's' não terminado

Hmmm ..

Eu acho, você assumindo \\\n ou \\\t como três barras invertidas lá, mas, na verdade, suas 2 barras invertidas e outros padrões

  backslash \\ newline \n tab \t 

também, / pode precisar escaping porque em s/.../ , / está usando para abrir e fechar partes.

então /\\\/\// seria \\ + \/ + \/ acordo com o seu exemplo atualizado

Substituir uma barra invertida por duas no meu Cygwin requer esta expressão:

sed -e “s | \\ | \\\\ | g”