Como usar variáveis entre aspas simples

11

Eu tenho um aplicativo que leva como atributos de entrada em aspas duplas incorporadas em aspas simples. Tomemos por exemplo este comando certo:

command -p 'cluster="cl1"'

Para automatizá-lo, criei um arquivo bash usando $CLUSTER como uma variável. Como deve ser meu comando? Em outras palavras, o que devo colocar em vez de cl1?

Por favor, note que, se eu modifiquei o comando acima, ele não será aceito. Por exemplo: command -p "cluster=cl1" não é aceito

    
por Mohamad-Jaafar NEHME 10.01.2015 / 00:36

2 respostas

8

Parece que seu comando talvez esteja configurando variáveis de ambiente com base em argumentos dados na linha de comando. Pode ser que você possa fazer:

CLUSTER=cl1; cluster=$CLUSTER command

... e defina seu ambiente para isso na invocação.

Caso contrário, as aspas de shell normalmente delimitam argumentos ou escapam de outros caracteres de shell especiais da interpretação de shell. Você pode conter (e, portanto, escapar) diferentes tipos de aspas em outros tipos com base em várias regras:

  • "''''" - uma string entre aspas pode conter qualquer número de aspas duras.
  • "\"" - uma barra invertida \ pode escapar de uma cotação de " dentro de uma sequência com " soft.
    • Neste contexto, uma barra invertida \ também escapa por si própria, o token de expansão \$ e \n ewlines, como indicado abaixo, mas é tratado literalmente de outra forma.
  • "${expand} and then some" - uma string entre aspas pode conter uma expansão interpretada $ do shell.
  • '"\' - a ' string com aspas strongs pode conter qualquer caractere diferente de uma citação com ' .
  • \ - uma barra invertida sem aspas escapará de qualquer caractere seguinte para interpretação literal - até mesmo outra barra invertida - exceto um \n ewline.
    • Em um caso de \n ewline, as barras invertidas \ e \n ewline são completamente removidas do comando interpretado resultante.
  • ${parameter+expand "$parameter"} - as aspas resultantes de uma expansão de shell quase nunca servem como marcadores delimitadores, exceto em alguns casos especiais. Não me aventuro a descrevê-las mais aqui.

Considero estranho que qualquer aplicativo interprete citações em seus argumentos de linha de comando. Tal prática não faz muito sentido - pelo menos para shells - o objetivo principal de uma citação é geralmente delimitar um argumento. Na invocação, no entanto, os argumentos são sempre já delimitados com -cNUL caracteres e, portanto, uma citação não pode servir a muitos propósitos.

Mesmo um shell normalmente só se incomodará em interpretar aspas em um de seus argumentos de invocação quando ele é chamado com uma opção " - o que denota que o primeiro operando é na verdade um shell script deve ser executado após a invocação. Este é um caso de entrada duas vezes avaliada .

Tudo isso dito, você pode fazer uma série de coisas para passar citações literais via argumentos na linha de comando. Por exemplo:

CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"

Como observei em um comentário anterior, você pode conter as " quotes dentro de uma expansão que é em si mesma " cotada.

CLUSTER=cl1; command -p "cluster=\"$CLUSTER\""

Você pode escapar do \ com uma barra invertida " na string $IFS entre aspas.

CLUSTER=cl1; command -p cluster='"'"$CLUSTER"'"'

Você pode alternar e concatenar estilos de citação para chegar ao resultado final desejado como @jimmij notas acima .

CLUSTER=cl1; ( set -f; IFS=; command -p cluster=\"$CLUSTER\" )

Você pode desativar geração de nome de arquivo e $expansion splitting - evitando assim a necessidade de citar sh -c "$scriptlet" - e, assim, apenas citar as aspas. Isso é provavelmente um exagero.

Por fim, há outro tipo de cotação de shell que pode ser usado. Como observei antes, a forma $scriptlet da invocação de shell é geralmente usada para fornecer o script de um shell na linha de comando. Quando sh -s se torna complicado - como quando aspas devem conter outras aspas - pode ser vantajoso usar um aqui-documento e -c - onde o shell é especificamente instruído para designar todos os operandos em> para os parâmetros posicionais, como faria em um caso stdin e, ainda assim, também para obter seu script em <<here-document .

Se o seu comando tiver que interpretar aspas desta maneira, considero que seria melhor fazê-lo em uma entrada de arquivo. Por exemplo:

CLUSTER=cl1
command --stdin <<-SCRIPT
    cluster="$CLUSTER"
SCRIPT

Se você não citar o delimitador de um " , todo o seu conteúdo será tratado quase exatamente como se fosse " soft-quoted - exceto que cat se dobra duas vezes não são tratados especialmente. Então, se executarmos o acima com %code% :

CLUSTER=cl1
cat <<-SCRIPT
        cluster="$CLUSTER"
SCRIPT

... imprime ...

cluster="cl1"
    
por 10.01.2015 / 05:01
1

Assim como o mikeserv escreveu:

 CLUSTER='"cl1"'; command -p "cluster=$CLUSTER" 

"Aspas duplas" a cada literal que contenha espaços / metacaracteres e todas as expansões: "$var" , "$(command "$var")" , "${array[@]}" , "a & b" . Use 'single quotes' para o código ou literal $'s: 'Costs $5 US' , ssh host 'echo "$HOSTNAME"' . Veja o link link
link

    
por 10.01.2015 / 00:49