Este comando:
echo '$$foo=bar' | sed -E "s/(\$\$foo=).*/\1$(echo hello)/"
saídas:
$$foo=bar
Se eu alterar as sed
aspas para simples e colocar o comando entre aspas duplas:
echo '$$foo=bar' | sed -E 's/(\$\$foo=).*/\1'"$(echo hello)"'/'
ele produz o resultado desejado:
$$foo=hello
Então eu acho que o problema está nas expressões regulares estendidas e aspas, a menos que eu esteja perdendo algo óbvio.
A concatenação de aspas simples e duplas na
sed
substituição de comandos é uma boa prática (sed 's/foo/'"$(command)"'/'
)?Como posso escapar de cifrões duplos
sed
com expressões regulares estendidas?
POSIX tem a dizer sobre a diferença em como
$
é interpretado em expressões regulares básicas e estendidas:Expressões regulares básicas (BREs):
Expressões regulares estendidas (EREs):
Conclusão: Em um BRE, o
$
caractere corresponde a si mesmo, a menos que seja o último caractere da expressão ou subexpressão (nesse caso, ancora a (sub)expressão no final da linha). Em um ERE, o$
personagem sempre ancora no final da linha.Quando você usa
seu ERE (desde que você usa
-E
) é($$foo=).*
e essa expressão nunca corresponderá (o texto POSIX acima contém o exemploe$f
que é semelhante).Seu comando
usa o BRE
$$foo
que corresponderá à string literal,$$foo
pois os$
caracteres não estão no final da expressão.Para corresponder a um único
$
caractere em uma expressão regular estendida, use\$
ou[$]
. Para escapar disso para o shell em uma string com aspas duplas, use\\\$
(uma barra invertida de escape seguida por um cifrão de escape) ou[\$]
, ou seja,ou
(A barra invertida em
\1
não precisa de escape, pois as barras invertidas só agem como um caractere de escape em uma string com aspas duplas se seguidas por um cifrão, backtick, aspas duplas, outra barra invertida ou uma nova linha; portanto, é literal, não uma referência\1
de escape1
; aqui ).Respostas curtas:
Você pode colocar aspas simples nos bits que precisam de aspas simples (e concatenar isso com uma string entre aspas duplas contendo suas expansões de shell), ou você escapa o que precisa ser escapado em uma única string com aspas duplas. Isso é uma questão de gosto. Eu estaria mais preocupado em usar uma substituição de comando na expressão, pois essa é uma vulnerabilidade de injeção de código, a menos que você tenha controle total sobre a string inserida.
\\\$
ou[\$]
em uma string com aspas duplas.\$
ou[$]
em uma única string entre aspas.