desenv-web-rp.com

Qual é a diferença entre aspas "...", '...', $ '...' e $ "..."?

Às vezes, vejo scripts usarem todas essas diferentes maneiras de citar algum texto: "...", '...', $'...' e $"...". Por que existem tantos tipos diferentes de cotação em uso?

Eles se comportam de maneira diferente ou afetam o que eu posso fazer dentro deles?

52
Michael Homer

Tudo isso significa algo diferente, e você pode escrever coisas diferentes dentro deles (ou as mesmas coisas, com significado diferente). Diferentes tipos de citação interpretam diferentes seqüências de escape dentro delas (\something) Ou permitem ou não permitem interpolações variáveis ​​($something) E outros tipos de expansão dentro delas.

Em resumo:

  • '...' É totalmente literal.
  • "..." Permite variáveis ​​e caracteres de aspas incorporados.
  • $'...' Realiza escape de caracteres como \n, Mas não expande variáveis.
  • $"..." É para traduções de idiomas humanos no Bash e no ksh.

'aspas simples'

Tudo o que você escreve entre aspas simples é tratado literalmente e não é processado. Barras invertidas e cifrões não têm significado especial lá. Isso significa que você não pode escapar pela barra invertida de um caractere (incluindo outras aspas simples!), Interpolar uma variável ou usar qualquer outro recurso do Shell.

Todos esses exemplos resultam literalmente no que está escrito entre as aspas:

'hello world'                     => hello world
'/pkg/bin:$PATH'                  => /pkg/bin:$PATH
'hello\nworld'                    => hello\nworld
'`echo abc`'                      => `echo abc`
'I\'dn\'t've'                     => I\dn'tve

A última é complicada - existem duas seqüências de caracteres entre aspas simples executadas em conjunto com algum texto sem aspas. O primeiro contém I\. O texto não citado dn\'t Contém uma única citação que é escapada no nível do Shell, portanto, não inicia uma string entre aspas e é incluída como um caractere literal (portanto, dn't). A string final citada é apenas ve. Todos eles são reunidos em uma única palavra da maneira usual em que o Shell funciona.

Um idioma comum para combinar texto literal e variáveis ​​é executá-los juntos assim:

'let x="'$PATH\"

vai resultar em

let x="/usr/bin:/bin"

como uma única palavra (é melhor citar $PATH também no caso - espaços ou caracteres brilhantes na variável valor podem ser processados ​​de outra forma - mas por uma questão de exemplo legível, não o tenho).


"aspas duplas"

Dentro de aspas duplas, dois tipos de expansão são processados ​​e você pode usar uma barra invertida para escapar caracteres para impedir que expansões ou escapes sejam processadas.

Existem duas categorias de expansão que ocorrem entre aspas duplas:

Dentro das aspas, uma barra invertida pode inibir essas expansões colocando-a antes de $ Ou `. Também pode escapar de uma citação dupla de fechamento, portanto, \" Inclui apenas " Em sua string ou em outra barra invertida. Qualquer outra barra invertida é preservada literalmente - não há escapatória para produzir outros caracteres e não é removida.

Alguns desses exemplos agem de maneira diferente de antes e outros não:

"hello world"                     => hello world
"/pkg/bin:$PATH"                  => /pkg/bin:/bin:/usr/bin
"hello\nworld"                    => hello\nworld
"hello\\nworld"                   => hello\nworld
"`echo abc`"                      => abc
"I\'dn\'t've"                     => I\'dn\'t've
"I'dn't've"                       => I'dn't've
"I\"dn\"t've"                     => I"dn"t've

$ 'cotação ANSI-C'

Esse tipo de citação permite que escapes de barra invertida no estilo C sejam processados, mas não variáveis ​​ou substituições incorporadas. É o tipo de citação apenas que suporta escapes de caracteres .

Esta é uma extensão do ksh, agora suportada no Bash, zsh e em alguns outros shells. Não é ainda parte do padrão POSIX e, portanto, os scripts portáteis não podem usá-lo, mas um script Bash ou ksh é gratuito.

Todas essas escapadas podem ser usadas com seus significados em C: \a, \b, \f, \n, \r, \t, \v, E o literal escapa \\, \', \" E \?. Eles também suportam as extensões \e (Caractere de escape) e no Bash e ksh \cx (O que seria inserido por Ctrl-x , por exemplo, \cM é retorno de carro). Os reservatórios têm uma série de extensões menores próprias.

Ele também permite quatro tipos de escape de caracteres genéricos:

  • \nnn, Um único byte com valor octal nnn
  • \xHH, Um único byte com valor hexadecimal [~ # ~] hh [~ # ~]
  • \uHHHH, O ponto de código Unicode cujo índice hexadecimal é [~ # ~] hhhh [~ # ~]
  • \UHHHHHHHH, O ponto de código Unicode cujo índice hexadecimal é [~ # ~] hhhhhhhh [~ # ~]

Todos esses dígitos são opcionais após o primeiro.

$ E ` Não têm significado e são preservados literalmente, portanto você não pode incluir uma variável lá.

$'hello world'                    => hello world
$'/pkg/bin:$PATH'                 => /pkg/bin:$PATH
$'hello\nworld'                   => hello
                                     world
$'`echo abc`'                     => `echo abc`
$'I\'dn\'t\'ve'                   => I'dn't've
$'\U1f574\u263A'                  => ????☺

Você pode simular a maioria dessas fugas usando o comando printf , embora o POSIX exija apenas \\, \a, \b, \f, \n, \r, \t, \v E \nnn Para trabalhar lá. Você pode usar a substituição de comando para incorporar printf entre aspas duplas, se necessário: "Path:$(printf '\t')$PATH".


$ "Tradução local"

Essa é uma extensão específica do ksh e do Bash para localizar seqüências de texto em idioma natural e procura a parte dentro das aspas em um catálogo de mensagens. Ele executa todas as expansões de aspas duplas primeiro. Se a sequência não for encontrada no banco de dados de tradução, ela será usada como sua própria tradução. A suposição interna é que as strings estão em inglês.

Você provavelmente não deseja usar este, mas se o vir, geralmente poderá tratá-lo como aspas duplas regulares.


Um ponto de observação é que existe um tipo de citação no que permite a expansão de parâmetros incorporados e o escape de caracteres incorporados. Na maioria dos casos em que você deseja isso, seria melhor (mais seguro) usar printf:

printf 'New path: \e[1m%s\e[0m' "/pkg/bin:$PATH:"

Isso separa claramente quais partes estão sujeitas a escape de caracteres e quais são os valores dos dados.

Outra é que todos esses estilos de citação criam uma única "Palavra" no Shell, a menos que[email protected] Ou uma expansão de matriz ${x[@]} Seja usada entre aspas duplas . Os dois formulários de aspas simples são sempre uma palavra e nunca se expandem mais.

68
Michael Homer