Cómo escapar de comillas simples dentro de cadenas entre comillas simples

Resuelto cons asked hace 15 años • 25 respuestas

Digamos que tienes un Bash aliascomo:

alias rxvt='urxvt'

que funciona bien.

Sin embargo:

alias rxvt='urxvt -fg '#111111' -bg '#111111''

no funcionará, y tampoco lo hará:

alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''

Entonces, ¿cómo terminas haciendo coincidir las comillas de apertura y cierre dentro de una cadena una vez que has escapado las comillas?

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''

parece desgarbado aunque representaría la misma cadena si se le permite concatenarlas así.

cons avatar Aug 09 '09 05:08 cons
Aceptado

Si realmente desea utilizar comillas simples en la capa más externa, recuerde que puede pegar ambos tipos de comillas. Ejemplo:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
 #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
 #                     12345       12345     12345       1234

Explicación de cómo '"'"'se interpreta como justo ':

  1. 'Finalice la primera cita que utilice comillas simples.
  2. "Comience la segunda cita, utilizando comillas dobles.
  3. 'Personaje citado.
  4. "Finalice la segunda cita utilizando comillas dobles.
  5. 'Comience la tercera cita, utilizando comillas simples.

Si no coloca ningún espacio en blanco entre (1) y (2), o entre (4) y (5), el shell interpretará esa cadena como una palabra larga.

liori avatar Aug 09 '2009 00:08 liori

TL;DR

Siempre reemplazo cada comilla simple incrustada con la secuencia: '\''(es decir: comillas, barra invertida, comillas) que cierra la cadena, agrega una comilla simple escapada y vuelve a abrir la cadena.

Más información sobre la conversión de cadenas con comillas simples incrustadas

A menudo preparo una función "quotify" en mis scripts Perl para que haga esto por mí. Los pasos serían:

s/'/'\\''/g    # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.

Esto prácticamente se ocupa de todos los casos.

La vida se vuelve más divertida cuando la introduces evalen tus scripts de shell. ¡Básicamente tienes que volver a cotizar todo nuevamente!

Por ejemplo, cree un script Perl llamado quotify que contenga las declaraciones anteriores:

#!/usr/bin/perl -pl
s/'/'\\''/g;
$_ = qq['$_'];

Luego úselo para generar una cadena entrecomillada correctamente:

$ quotify
urxvt -fg '#111111' -bg '#111111'

Resultado:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

Que luego se puede copiar/pegar en el comando alias:

alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

(Si necesita insertar el comando en una evaluación, ejecute quotify nuevamente:

$ quotify
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

Resultado:

'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

Que se puede copiar/pegar en una evaluación :

eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''
Adrian Pronk avatar Aug 22 '2009 05:08 Adrian Pronk

Dado que la sintaxis de Bash 2.04$'string' permite un conjunto límite de escapes.

Desde Bash 4.4, $'string'también permite el conjunto completo de escapes estilo C , lo que hace que el comportamiento difiera ligeramente de $'string'versiones anteriores. (Anteriormente $('string')se podía utilizar el formulario.)

Un ejemplo simple en Bash 2.04 y posteriores:

  $> echo $'aa\'bb'
  aa'bb

  $> alias myvar=$'aa\'bb'
  $> alias myvar
  alias myvar='aa'\''bb'

En tu caso:

$> alias rxvt=$'urxvt -fg \'#111111\' -bg \'#111111\''
$> alias rxvt
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

Las secuencias de escape comunes funcionan como se esperaba:

\'     single quote
\"     double quote
\\     backslash
\n     new line
\t     horizontal tab
\r     carriage return

A continuación se copia y pega la documentación relacionada de man bash(versión 4.4):

Las palabras del formato $'cadena' se tratan de forma especial. La palabra se expande a una cadena, con caracteres de escape con barra invertida reemplazados según lo especificado por el estándar ANSI C. Las secuencias de escape de barra invertida, si están presentes, se decodifican de la siguiente manera:

    \a     alert (bell)
    \b     backspace
    \e
    \E     an escape character
    \f     form feed
    \n     new line
    \r     carriage return
    \t     horizontal tab
    \v     vertical tab
    \\     backslash
    \'     single quote
    \"     double quote
    \?     question mark
    \nnn   the eight-bit character whose value is the octal
           value nnn (one to three digits)
    \xHH   the eight-bit character whose value is the hexadecimal
           value HH (one or two hex digits)
    \uHHHH the Unicode (ISO/IEC 10646) character whose value is
           the hexadecimal value HHHH (one to four hex digits)
    \UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value
               is the hexadecimal value HHHHHHHH (one to eight
               hex digits)
    \cx    a control-x character

El resultado ampliado está entre comillas simples, como si el signo del dólar no hubiera estado presente.


Consulte Cotizaciones y escape: cadenas similares a ANSI C en la wiki de bash-hackers.org para obtener más detalles. También tenga en cuenta que el archivo "Bash Changes" ( descripción general aquí ) menciona muchos cambios y correcciones de errores relacionados con el $'string'mecanismo de cotización.

Según Unix y Linux ' ¿Cómo utilizar un carácter especial como uno normal? , debería funcionar (con algunas variaciones) en Bash, Z shell , mksh, ksh93, FreeBSD y BusyBox sh.

mj41 avatar May 17 '2013 08:05 mj41