Cómo escapar de comillas simples dentro de cadenas entre comillas simples
Digamos que tienes un Bash alias
como:
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í.
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 '
:
'
Finalice la primera cita que utilice comillas simples."
Comience la segunda cita, utilizando comillas dobles.'
Personaje citado."
Finalice la segunda cita utilizando comillas dobles.'
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.
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 eval
en 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'\''\'\'''\'''\'''
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.