Respostas:
Use um delimitador regex alternativo, pois sed
permite que você use qualquer delimitador ( incluindo caracteres de controle ):
sed "s~$var~replace~g" $file
$var
Uma resposta puramente bash: use a expansão do parâmetro para fazer o escape de qualquer barra invertida na variável:
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
${parameter/pattern/string}
. Portanto, neste caso, o parâmetro é var
, o padrão é /\/
e a string é \\/
. Todas as instâncias do padrão são substituídas porque o padrão começa com a /
.
Usar /
em sed como um delimitador entrará em conflito com as barras na variável quando substituída e, como resultado, você obterá um erro. Uma maneira de contornar isso é usar outro delimitador que seja exclusivo de todos os caracteres dessa variável.
var="/Users/Documents/name/file"
você pode usar o caractere octotorpe que se adapte à ocasião (ou qualquer outro caractere que não seja /
para facilidade de uso)
sed "s#$var#replace#g"
ou
sed 's#$'$var'#replace#g'
isto é adequado quando a variável não contém espaços
ou
sed 's#$"'$var'"#replace#g'
É mais sensato usar o acima, uma vez que estamos interessados em substituir o que quer que esteja nessa variável apenas em comparação com aspas duplas de todo o comando, o que pode fazer com que seu shell interprete qualquer caractere que possa ser considerado um caractere especial de shell para o shell.
$var
contém ~
, obviamente você precisará escolher um delimitador diferente. O erro "não terminado" parece que $var
contém uma nova linha; você pode consertá-lo fazendo escape de barra invertida a cada nova linha no valor, mas não acho que isso seja totalmente portátil. Em geral, isso não está relacionado ao problema de barras no valor.
sed -i "s~blah~$var~g" file
com aspas apenas em torno do sed
script real .
Esta é uma pergunta antiga, mas nenhuma das respostas aqui discute as operações, a não ser s/from/to/
com muitos detalhes.
A forma geral de uma sed
declaração é
*address* *action*
onde o endereço pode ser um intervalo regex ou um intervalo de número de linha (ou vazio, caso em que a ação é aplicada a cada linha de entrada). Então por exemplo
sed '1,4d' file
irá deletar as linhas 1 a 4 (o endereço é o intervalo do número da linha 1,4
e a ação é o d
comando deletar); e
sed '/ick/,$s/foo/bar/' file
irá substituir a primeira ocorrência de foo
por bar
em qualquer linha entre a primeira correspondência na regex ick
e o final do arquivo (o endereço é o intervalo /ick/,$
e a ação é o s
comando substituto s/foo/bar/
).
Neste contexto, se ick
veio de uma variável, você poderia fazer
sed "/$variable/,\$s/foo/bar/"
(observe o uso de aspas duplas em vez de simples, para que o shell possa interpolar a variável e a necessidade de colocar o cifrão literal entre aspas duplas), mas se a variável contiver uma barra, você obterá um erro de sintaxe. (O shell expande a variável e, em seguida, passa a string resultante para sed
; portanto, sed
vê apenas o texto literal - não tem nenhum conceito das variáveis do shell.)
A solução é usar um delimitador diferente (onde obviamente você precisa ser capaz de usar um caractere que não pode ocorrer no valor da variável), mas ao contrário do s%foo%bar%
caso, você também precisa de uma barra invertida antes do delimitador se quiser usar um delimitador do que o padrão /
:
sed "\\%$variable%,\$s/foo/bar/" file
(entre aspas simples, uma única barra invertida seria obviamente suficiente); ou você pode escapar separadamente de cada barra no valor. Esta sintaxe específica é apenas Bash:
sed "/${variable//\//\\/}/,\$s/foo/bar/" file
ou se você usar um shell diferente, tente
escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file
Para maior clareza, se $variable
contiver a string 1/2
, os comandos acima seriam equivalentes a
sed '\%1/2%,$s/foo/bar/' file
no primeiro caso, e
sed '/1\/2/,$s/foo/bar/' file
no segundo.
Use Perl, onde as variáveis são cidadãos de primeira classe, não apenas macros de expansão:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p
lê a entrada linha por linha e imprime a linha após o processamento\Q
cita todos os metacaracteres na seguinte string (não necessária para o valor apresentado aqui, mas necessária se o valor contiver [
ou alguns outros valores especiais para expressões regulares)