Esta questão não é sobre como escrever uma literal de string com escape apropriado. Não consegui encontrar nenhuma pergunta relacionada que não seja sobre como escapar de variáveis para consumo direto em um script ou em outros programas.
Meu objetivo é habilitar um script para gerar outros scripts. Isso ocorre porque as tarefas nos scripts gerados serão executadas de 0 a n vezes em outra máquina, e os dados dos quais eles são gerados podem ser alterados antes de serem executados (novamente), fazendo as operações diretamente, através de uma rede não funciona.
Dada uma variável conhecida que pode conter caracteres especiais, como aspas simples, preciso escrevê-la como um literal de string totalmente escapado, por exemplo, uma variável que foo
contenha bar'baz
deve aparecer no script gerado como:
qux='bar'\''baz'
que seria escrito anexando "qux=$foo_esc"
às outras linhas de script. Eu fiz isso usando Perl assim:
foo_esc="'`perl -pe 's/('\'')/\\1\\\\\\1\\1/g' <<<"$foo"`'"
mas isso parece exagero.
Não tive sucesso em fazê-lo apenas com o bash. Eu tentei muitas variações destes:
foo_esc="'${file//\'/\'\\\'\'}'"
foo_esc="'${file//\'/'\\''}'"
mas as barras extras aparecem na saída (quando o faço echo "$foo"
) ou causam um erro de sintaxe (esperando uma entrada adicional se feita a partir do shell).
alias
e / ouset
razoavelmente universalalias "varname=$varname" varname
ouvar=value set
Respostas:
O Bash tem uma opção de expansão de parâmetro exatamente para este caso :
Então, neste caso:
Isso é suportado no Bash 4.4 ou superior. Existem várias opções para outras formas de expansão e também para gerar especificamente instruções de atribuição completas (
@A
).fonte
bad substitution
."${foo:q}"
."${foo@Q}"
trabalho!O Bash fornece um especificador de formato
printf
interno%q
, que executa o escape de shell para você, mesmo nas versões mais antigas (<4.0) do Bash:Este truque também pode ser usado para retornar matrizes de dados de uma função:
Observe que o Bash
printf
embutido é diferente doprintf
utilitário fornecido com a maioria dos sistemas operacionais semelhantes ao Unix. Se, por algum motivo, oprintf
comando chamar o utilitário em vez do incorporado, você sempre poderá executarbuiltin printf
.fonte
'Ne'\''er do well'
, etc., ou seja, citações incluídas na saída.[[ 'Ne'\''er do well' == Ne\'er\ do\ well ]] && echo 'equivalent!'
,equivalent!
'hello'
resulta em um valor incorreto''\''hello''
, que possui uma sequência vazia inicial desnecessária (as duas primeiras aspas simples) e uma aspas simples à direita.$'escape-these-chars'
é o recurso de citação ANSI-C do Bash que faz com que todos os caracteres dentro da string especificada sejam escapados. Assim, para criar facilmente um literal de cadeia que contenha uma nova linha dentro do nome (por exemplo$'first-line\nsecond-line')
, o uso\n
neste constructo.Eu acho que não fiz RTFM. Isso pode ser feito da seguinte maneira:
Então
echo "$foo_esc"
dá o esperado'bar'\''baz'
Como eu estou realmente usando isso é com uma função:
Modificando isso para usar o
printf
built-in da solução de Dejay:fonte
Existem várias soluções para citar um valor var:
alias
Na maioria dos shells (onde o alias está disponível) (exceto csh, tcsh e provavelmente outros como o csh):
Sim, isso funciona em várias
sh
conchas como traço ou cinza.set
Também na maioria dos shells (novamente, não no csh):
typeset
Em algumas conchas (ksh, bash e zsh, pelo menos):
exportar
Primeiro faça:
Então use:
ksh
export -p | grep 'qux='
bashexport -p | grep 'qux='
zsh
export -p qux
pode-se citar
bash
echo "${qux@Q}"
zsh
echo "${(qq)qux}"
# de um a quatro q's.fonte
grep
comexport
ouset
podem quebrar em variáveis que contêm novas linhas incorporadas.