¿Cuál es la diferencia entre las citas "...", '...', $ '...' y $ "..."?


49

A veces veo scripts utilizan todas estas diferentes formas de citar un texto: "...", '...', $'...', y $"...". ¿Por qué se utilizan tantos tipos diferentes de cotizaciones?

¿Se comportan de manera diferente o afectan lo que puedo hacer dentro de ellos?


1
Posible duplicado entre sitios. Esta respuesta proporciona un resumen de (o enlaces a) la semántica de todos los diferentes tipos de citas.
Chepner

Respuestas:


66

Todos estos significan algo diferente, y puedes escribir diferentes cosas dentro de ellos (o las mismas cosas, con un significado diferente). Diferentes tipos de comillas interpretan diferentes secuencias de escape dentro de ellas ( \something), o permiten o no interpolaciones variables ( $something) y otros tipos de expansión dentro de ellas.

En breve:

  • '...' Es completamente literal.
  • "..." permite tanto variables como caracteres de comillas incrustados.
  • $'...'realiza escapes de caracteres como \n, pero no expande variables.
  • $"..." es para traducciones en lenguaje humano en Bash y ksh.

'Comillas simples'

Lo que escriba entre comillas simples se trata literalmente y no se procesa en absoluto. Las barras invertidas y los signos de dólar no tienen un significado especial allí. Esto significa que no puede hacer una barra invertida para escapar de un carácter (¡incluidas otras comillas simples!), Interpolar una variable o usar cualquier otra función de shell.

Todos estos ejemplos dan como resultado literalmente lo que está escrito entre comillas:

'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

El último es complicado: hay dos cadenas entre comillas simples que se ejecutan junto con algún texto sin comillas. El primero contiene I\. El texto sin comillas dn\'tcontiene una comilla simple que se escapa a nivel de shell , por lo que no comienza una cadena entre comillas y se incluye como un carácter literal (entonces, dn't). La cadena final citada es justa ve. Todos ellos se juntan en una sola palabra de la forma habitual en que funciona el shell.

Un modismo algo común para combinar texto literal y variables es ejecutarlos juntos de la siguiente manera:

'let x="'$PATH\"

resultará en

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

como una sola palabra (mejor también entre comillas dobles por $PATHsi acaso; los espacios o los caracteres globales en el valor de la variable pueden procesarse de otra manera , pero por el bien de un ejemplo legible no lo he hecho).


"Doble comillas"

Dentro de las comillas dobles, se procesan dos tipos de expansión, y puede usar una barra invertida para escapar de los caracteres y evitar que se procesen expansiones o escapes.

Hay dos categorías de expansión que ocurren entre comillas dobles:

Dentro de las comillas, una barra invertida puede inhibir esas expansiones poniéndola antes de $o `. También puede escapar de una comilla doble de cierre, por lo que \"incluye solo "en su cadena u otra barra invertida. Cualquier otra barra diagonal inversa se conserva literalmente: no hay escapes para producir otros caracteres, y no se elimina.

Algunos de estos ejemplos actúan de manera diferente a antes, y otros no:

"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

$ 'Cotización ANSI-C'

Este tipo de comillas permite procesar los escapes de barra invertida de estilo C, pero no las variables o sustituciones incrustadas. Es el único tipo de cita que admite escapes de caracteres .

Esta es una extensión de ksh, ahora compatible con Bash, zsh y algunos otros shells también. Todavía no es parte del estándar POSIX y, por lo tanto, los scripts máximamente portátiles no pueden usarlo, pero un script Bash o ksh es gratuito.

Todos estos escapes se puede utilizar con sus significados C: \a, \b, \f, \n, \r, \t, \v, y los escapes literales \\, \', \", y \?. También admiten las extensiones \e(carácter de escape) y en Bash y ksh \cx(lo que se introduciría con Ctrl-x , por ejemplo, \cMes el retorno de carro). Los proyectiles tienen una gama de extensiones menores propias.

También permite cuatro tipos de escapes de caracteres genéricos:

  • \nnn, un solo byte con valor octal nnn
  • \xHH, un solo byte con valor hexadecimal HH
  • \uHHHH, el punto de código Unicode cuyo índice hexadecimal es HHHH
  • \UHHHHHHHH, el punto de código Unicode cuyo índice hexadecimal es HHHHHHHH

Todos esos dígitos son opcionales después del primero.

$y `no tienen significado y se conservan literalmente, por lo que no puede incluir una variable allí.

$'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'                  => 🕴☺

La mayor parte de estos escapes se puede simular mediante el printfcomando , aunque sólo requiere POSIX \\, \a, \b, \f, \n, \r, \t, \v, y \nnnpara trabajar allí. Se puede utilizar la sustitución de comandos para incrustar un printfcomillas dobles si es necesario: "Path:$(printf '\t')$PATH".


$ "Traducción local"

Esta es una extensión específica de ksh y Bash para localizar cadenas de texto en lenguaje natural, y busca la parte dentro de las comillas en un catálogo de mensajes. Realiza todas las expansiones de comillas dobles primero. Si la cadena no se encuentra en la base de datos de traducción, se usa como su propia traducción. La suposición incorporada es que las cadenas están en inglés.

Probablemente no quiera usar este, pero si lo ve, generalmente puede tratarlo como comillas dobles regulares.


Un punto a destacar es que no hay ningún tipo de cita que permita tanto la expansión de parámetros incrustados como los escapes de caracteres incrustados. En la mayoría de los casos en los que desearía eso, sería mejor (más seguro) usar printf:

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

Esto separa claramente qué partes están sujetas al escape de caracteres y cuáles son valores de datos.

Otra es que todos estos estilos de comillas crean una sola "palabra" en el shell, a menos que se use $@ una expansión de matriz ${x[@]}dentro de comillas dobles. Ambas formas de comillas simples son siempre una palabra y nunca se expandieron más.


$"..."también es de ksh93, agregado a bash en 2.0.
Stéphane Chazelas

No hay \cXadentro zsh. Está \CXo \C-Xallí ( \cya tiene un significado especial echo)
Stéphane Chazelas

'let x="'$PATH\"que está mal en contextos de lista en conchas distintas de zshcomo $PATHno se cita (por lo que estaría sujeto a dividir + glob que no quiere aquí).
Stéphane Chazelas

Es posible que desee aclarar que está hablando de conchas tipo Korn, el procesamiento de cotizaciones es diferente en csh, rc, pescado ...
Stéphane Chazelas

@ StéphaneChazelas Definir "contexto de lista".
Isaac
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.