Escapando a barra e a barra invertida com sed

3

Eu tenho a seguinte string: /tmp/test/folder1/test.txt

Desejo usar sed para substituir / por \/ - por exemplo:

\/tmp\/test\/folder1\/test.txt

Então eu emito:

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

Embora retorne:

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

Estou escapando da barra invertida e da barra invertida - por isso não tenho certeza de onde estou errado aqui

    
por James 19.07.2017 / 17:56

3 respostas

10

Você precisa escapar (com contrabaixo \ ) todas as barras substituídas / e todas as barras invertidas \ separadamente, portanto:

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

mas isso é bastante ilegível.

No entanto, sed permite usar quase qualquer caractere como um separador em vez de / , isso é especialmente útil quando se deseja substituir a barra / , como no seu caso, usando, por exemplo, semicolon ; como separador, o comando se tornaria mais simples:

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

Outros casos:

  • Se alguém quiser ficar com a barra como separador e usar aspas duplas, todas as barras invertidas com escape precisarão ser escapadas mais uma vez para preservar seus valores literais:

    echo "/tmp/test/folder1/test.txt" | sed "s/\//\\\//g"
    
  • se não quisermos citações, será necessária outra barra invertida:

    echo "/tmp/test/folder1/test.txt" | sed s/\//\\\//g
    
por 19.07.2017 / 18:02
5

Ou, se o valor estiver em uma variável de shell (bash):

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

A primeira // expansão de parâmetro , dizendo para substitua all com a substituição. O próximo \/ é o% escape/ para corresponder e o \\/ é um \ seguido por um / como substituto.

    
por 19.07.2017 / 18:16
0

A solução final será esta:

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

Mas para explicar como chegar lá:
Sim, você estava perdendo uma barra invertida:

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

Espero que um espaço deixe claro:

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

Mas, se você tivesse que alterar o delimitador de sed para : (por exemplo):

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

Mas isso não é estritamente correto, pois o (agora não é especial) / não precisa de "scaping":

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

E, se você usar aspas simples em vez de aspas duplas, o shell não alterará o valor duplo \ para um, portanto, menos \ estará correto:

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

O que é bem mais limpo.

    
por 20.07.2017 / 06:49

Tags