Como você passa uma variável contendo barras como um padrão para sed
?
Por exemplo, se eu tiver a seguinte variável:
var="/Users/Documents/name/file"
Eu quero passar para sed
:
sed "s/$var/replace/g" "$file"
No entanto, recebo erros. Como posso contornar o problema?
$var
Uma resposta puramente bash: use a expansão do parâmetro para fazer o escape de qualquer barra invertida na variável:
fonte
${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/
.Outra maneira de fazer isso, embora mais feia do que a resposta de anubhava, é escapar de todas as barras invertidas em
var
usando outrosed
comando:então, isso vai funcionar:
fonte
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.você pode usar o caractere octotorpe que se adapte à ocasião (ou qualquer outro caractere que não seja
/
para facilidade de uso)ou
isto é adequado quando a variável não contém espaços
ou
É 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.
fonte
$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 dosed
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 é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
irá deletar as linhas 1 a 4 (o endereço é o intervalo do número da linha
1,4
e a ação é od
comando deletar); eirá substituir a primeira ocorrência de
foo
porbar
em qualquer linha entre a primeira correspondência na regexick
e o final do arquivo (o endereço é o intervalo/ick/,$
e a ação é os
comando substitutos/foo/bar/
).Neste contexto, se
ick
veio de uma variável, você poderia fazer(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/
:(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:
ou se você usar um shell diferente, tente
Para maior clareza, se
$variable
contiver a string1/2
, os comandos acima seriam equivalentes ano primeiro caso, e
no segundo.
fonte
Use Perl, onde as variáveis são cidadãos de primeira classe, não apenas macros de expansão:
-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)fonte