No meu script bash, tenho uma string externa (recebida do usuário), que devo usar no padrão sed.
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
Como posso escapar da $REPLACE
string para que ela seja aceita com segurança sed
como uma substituição literal?
NOTA: A KEYWORD
é uma substring mudo sem partidas etc. Não é fornecido pelo usuário.
outputvar="${inputvar//"$txt2replace"/"$txt2replacewith"}".
Respostas:
Aviso : isso não considera novas linhas. Para uma resposta mais aprofundada, consulte esta pergunta SO . (Obrigado, Ed Morton e Niklas Peter)
Observe que escapar de tudo é uma má ideia. Sed precisa que muitos caracteres sejam escapados para obter seu significado especial. Por exemplo, se você escapar um dígito na sequência de substituição, ela retornará para uma referência anterior.
Como Ben Blank disse, existem apenas três caracteres que precisam ser escapados na sequência de substituição (escapam a si mesmos, barra invertida para final de instrução e & para substituir todos):
Se você precisar escapar da
KEYWORD
sequência, é o seguinte:E pode ser usado por:
Lembre-se, se você usar um caractere diferente de
/
delimitador, precisará substituir a barra nas expressões acima pelo caractere que está usando. Veja o comentário de PeterJCLaw para explicação.Editado: devido a alguns casos de canto anteriormente não contabilizados, os comandos acima foram alterados várias vezes. Verifique o histórico de edições para obter detalhes.
fonte
KEYWORD
, em GNU sed , aqui estão mais 2 caracteres^
,$
não mencionados acima:s/[]\/$*.^|[]/\\&/g
A='foo"bar' echo $A | sed s/$A/baz/
em . bash o aspas são tratados apenas como o 'foo' e 'bar' em torno dele.O comando sed permite que você use outros caracteres em vez de
/
separador:As aspas duplas não são um problema.
fonte
.
que de outra forma tem um significado especial. Eu editei sua resposta.sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
comsed '|CLIENTSCRIPT="foo"|a CLIENTSCRIPT2="hello"' file
e isso não faz o mesmo.s
comando (como substituto) do sed permite que você use outros caracteres em vez de / como um separador. Além disso, isso seria uma resposta para como usar o sed on URL com caracteres de barra. Ele não responde à pergunta do OP como escapar de uma string inserida por um usuário, que pode conter /, \, mas também # se você decidir usá-la. E, além disso, o URI também pode conter #Os únicos três caracteres literais que são tratados especialmente na cláusula de substituição são
/
(para fechar a cláusula),\
(para escapar dos caracteres, referência anterior, etc.) e&
(para incluir a correspondência na substituição). Portanto, tudo que você precisa fazer é escapar desses três caracteres:Exemplo:
fonte
Com base nas expressões regulares do Pianosaurus, criei uma função bash que escapa à palavra-chave e à substituição.
Veja como você o usa:
fonte
man echo
), fazendo com que o pipe se comporte inesperadamente quando seu argumento$1
começa com um traço. Em vez disso, você pode iniciar o seu pipeprintf '%s\n' "$1"
.É um pouco tarde para responder ... mas há uma maneira muito mais simples de fazer isso. Basta alterar o delimitador (ou seja, o caractere que separa os campos). Então, em vez de
s/foo/bar/
você escrevers|bar|foo
.E, aqui está a maneira mais fácil de fazer isso:
A saída resultante é desprovida dessa desagradável cláusula DEFINER.
fonte
&
e `` ainda deve ser escapado, assim como o delimitador, o que for escolhido.$
na string prestes a ser alterada e manter o significado da$
string de substituição. digamos que quero mudar$XXX
para o valor da variável$YYY
,sed -i "s|\$XXX|$YYY|g" file
funciona bem.Acontece que você está fazendo a pergunta errada. Eu também fiz a pergunta errada. A razão pela qual está errado é o início da primeira frase: "No meu script bash ...".
Eu tive a mesma pergunta e cometi o mesmo erro. Se você estiver usando o bash, não precisará usar o sed para fazer substituições de strings (e é muito mais fácil usar o recurso de substituição incorporado ao bash).
Em vez de algo como, por exemplo:
você pode usar os recursos do bash exclusivamente:
fonte
$A
e$B
não está entre aspas, mas não está. As aspas dentro${}
do não coincidem com as aspas fora dele.var='has space'
) -OUTPUT=${INPUT//"$A"/"$B"}
é seguro.Use awk - é mais limpo:
fonte
awk
é que ele não tem nada parecidosed -i
, o que é extremamente útil 99% do tempo.Aqui está um exemplo de um AWK que usei há um tempo atrás. É um AWK que imprime novos AWKS. Sendo AWK e SED semelhantes, pode ser um bom modelo.
Parece excessivo, mas de alguma forma essa combinação de aspas funciona para manter o 'impresso como literal. Então, se bem me lembro, as variáveis estão rodeadas de aspas como esta: "$ 1". Experimente, deixe-me saber como funciona com o SED.
fonte
Eu tenho uma melhoria sobre a função sedeasy, que quebrará com caracteres especiais como tab.
Então, o que é diferente?
$1
e$2
entre aspas para evitar expansões de shell e preservar tabulações ou espaços duplos.Tubulação adicional
| sed -e 's:\t:\\t:g'
(eu gosto:
como token) que transforma uma guia\t
.fonte
Estes são os códigos de escape que eu encontrei:
fonte
não se esqueça de todo o prazer que ocorre com a limitação da concha "e '
então (em ksh)
fonte
Se você está apenas procurando substituir o valor Variável no comando sed, basta remover o Exemplo:
fonte
Se acontecer de você estar gerando uma senha aleatória para passar para
sed
substituir o padrão, escolha ser cuidadoso sobre qual conjunto de caracteres na sequência aleatória. Se você escolher uma senha criada codificando um valor como base64, haverá apenas um caractere possível na base64 e também um caractere especial nosed
padrão de substituição. Esse caractere é "/" e é facilmente removido da senha que você está gerando:fonte
Uma maneira mais fácil de fazer isso é simplesmente construir a string antes da mão e usá-la como parâmetro para
sed
fonte
REPLACE=/
dásed: -e expression #1, char 12: unknown option to `s'