Escape de uma variável para uso como conteúdo de outro script

7

Esta questão é não sobre como escrever um literal de string corretamente escapado. Não encontrei nenhuma questão relacionada que não seja sobre como escapar de variáveis para consumo direto em um script ou por outros programas.

Meu objetivo é permitir que um script gere 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 a partir dos quais são gerados podem mudar antes de serem executados (novamente), fazendo o operações diretamente, através de uma rede não funcionará.

Dada uma variável conhecida que pode conter caracteres especiais, como aspas simples, preciso escrevê-la como um literal de string totalmente evasivo, por exemplo, uma variável foo contendo bar'baz deve aparecer no script gerado como:

qux='bar'\''baz'

que seria escrito anexando "qux=$foo_esc" às outras linhas do script. Eu fiz isso usando o Perl assim:

foo_esc="''perl -pe 's/('\'')/\1\\\1\1/g' <<<"$foo"''"

mas isso parece um exagero.

Eu não tive sucesso em fazê-lo apenas com o bash. Eu tentei muitas variações destes:

foo_esc="'${file//\'/\'\\'\'}'"
foo_esc="'${file//\'/'\''}'"

mas barras extras aparecem na saída (quando eu faço echo "$foo" ) ou causam um erro de sintaxe (esperando entrada adicional se feito a partir do shell).

    
por Walf 18.07.2017 / 07:14

4 respostas

2

Acho que não fiz RTFM. Isso pode ser feito assim:

q_mid=\'\\'\'
foo_esc="'${foo//\'/$q_mid}'"

Em seguida, echo "$foo_esc" fornece o esperado 'bar'\''baz'

Como estou realmente usando é com uma função:

function esc_var {
    local mid_q=\'\\'\'
    printf '%s' "'${1//\'/$mid_q}'"
}

...

foo_esc="'esc_var "$foo"'"
    
por 18.07.2017 / 07:14
10

O Bash tem uma opção de expansão de parâmetro para exatamente este caso :

${parameter@Q} The expansion is a string that is the value of parameter quoted in a format that can be reused as input.

Então, neste caso:

foo_esc="${foo@Q}"

Isso é suportado no Bash 4.4 e acima. Existem várias opções para outras formas de expansão e para gerar especificamente instruções de atribuição completas ( @A ).

    
por 18.07.2017 / 08:11
1

O Bash fornece um printf integrado com o especificador de formato %q , que executa o shell escape para você, mesmo em versões mais antigas (< 4.0) do Bash:

printf '[%q]\n' "Ne'er do well"
# Prints [Ne\'er\ do\ well]

printf '[%q]\n' 'Sneaky injection $( whoami ) 'ls /root''
# Prints [Sneaky\ injection\ \$\(\ whoami\ \)\ \'ls\ /root\']

Esse truque também pode ser usado para retornar matrizes de dados de uma função:

function getData()
{
  printf '%q ' "He'll say hi" 'or 'whoami'' 'and then $( byebye )'
}

declare -a DATA="( $( getData ) )"
printf 'DATA: [%q]\n' "${DATA[@]}"
# Prints:
# DATA: [He\'ll\ say\ hi]
# DATA: [or\ \'whoami\']
# DATA: [and\ then\ \$\(\ byebye\ \)]

Observe que o Bash printf builtin é diferente do utilitário printf , fornecido com a maioria dos sistemas operacionais semelhantes ao Unix. Se, por algum motivo, o comando printf invocar o utilitário em vez do incorporado, você sempre poderá executar builtin printf .

    
por 28.07.2018 / 05:13
1

Existem várias soluções para citar um valor var:

  1. alias
    Na maioria das shells (onde alias está disponível) (exceto csh, tcsh e provavelmente outros como csh):

    $ alias qux=bar\'baz
    $ alias qux
    qux='bar'\''baz'
    

    Sim, isso funciona em muitas camadas iguais a sh , como traços ou cinzas.

  2. set
    Também na maioria dos shells (novamente, não csh):

    $ qux=bar\'baz
    $ set | grep '^qux='
    qux='bar'\''baz'
    
  3. tipografado
    Em alguns shells (ksh, bash e zsh, pelo menos):

    $ qux=bar\'baz
    $ typeset -p qux
    typeset qux='bar'\''baz'             # this is zsh, quoting style may
                                         # be different for other shells.
    
  4. exportar
    Primeiro faça:

    export qux=bar\'baz
    

    Em seguida, use: export -p | grep 'qux=' export -p | grep 'qux='
    export -p qux

  5. Citação echo "${qux@Q}"
    echo "${(qq)qux}" # de um a quatro q's podem ser usados. / p>

por 02.08.2018 / 08:28