Pregunta ¿Cómo escapar de las comillas simples dentro de las cadenas citadas?


Digamos, tienes una fiesta alias me gusta:

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 de las comillas?

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

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


724
2017-08-08 22:50


origen


Respuestas:


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

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

Explicación de cómo '"'"' es interpretado como solo ':

  1. ' Fin de la primera cita que utiliza comillas simples.
  2. " Comience la segunda cita, usando comillas dobles.
  3. ' Personaje citado
  4. " Fin de la segunda cita, usando comillas dobles.
  5. ' Comience la tercera cita, usando comillas simples.

Si no coloca espacios en blanco entre (1) y (2), o entre (4) y (5), el intérprete interpretará esa cadena como una palabra larga.


1067
2017-08-09 00:52



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


A menudo hago funcionar una función "quotify" en mis scripts de Perl para hacer 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 presentas eval en tus guiones de shell. ¡Esencialmente tienes que volver a calcular todo de nuevo!

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

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

luego utilícelo para generar una cadena citada correctamente:

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

resultado:

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

que luego puede copiarse / pegarse en el comando alias:

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

(Si necesita insertar el comando en un eval, ejecute el comando 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'\''\'\'''\'''\'''

196
2017-08-22 05:30



Desde Bash 2.04 sintaxis $'string' (en lugar de simplemente 'string'; advertencia: no confundas con $('string')) es otro mecanismo de cotización que permite Secuencias de escape tipo ANSI C y hacer la expansión a la versión de una sola cita.

Ejemplo simple:

  $> 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 encuentra la copia y la documentación relacionada pegada de man bash (versión 4.4):

Las palabras de la forma $ 'cadena' se tratan especialmente. La palabra se expande a cadena, con caracteres de barra invertida escapados como se especifica en 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 se cita por separado, como si el signo de dólar no hubiera estado presente.


Ver Citas y escapes: cadenas similares a ANSI C en la wiki de bash-hackers.org para más detalles. También tenga en cuenta que "Cambios Bash" archivo (descripción general aquí) menciona mucho los cambios y las correcciones de errores relacionados con $'string' mecanismo de cotización.

De acuerdo con unix.stackexchange.com ¿Cómo usar un personaje especial como uno normal?debería funcionar (con algunas variaciones) en bash, zsh, mksh, ksh93 y FreeBSD y busybox sh.


113
2018-05-17 08:56



No veo la entrada en su blog (enlace pls?) Pero de acuerdo con el manual de referencia gnu:

Encerrar personajes en comillas simples   ('' ') Conserva el valor literal de   cada personaje dentro de las comillas. UN   la comilla simple no puede ocurrir entre   comillas simples, incluso cuando están precedidas por un   barra invertida.

así que bash no entenderá:

alias x='y \'z '

sin embargo, puedes hacer esto si rodeas con comillas dobles:

alias x="echo \'y "
> x
> 'y

42
2017-08-08 23:07



Puedo confirmar que estoy usando '\'' para una comilla simple dentro de una cadena de una sola cita funciona en Bash, y se puede explicar de la misma manera que el argumento "pegado" de la primera parte del hilo. Supongamos que tenemos una cadena entre comillas 'A '\''B'\'' C' (todas las citas aquí son comillas simples). Si se pasa a eco, imprime lo siguiente: A 'B' C. En cada '\'' la primera cita cierra la cadena actual entre comillas simples, la siguiente \' pega una única cotización a la cadena anterior (\' es una forma de especificar una cita única sin iniciar una cadena entrecomillada), y la última cita abre otra cadena entre comillas simples.


26
2017-08-03 07:54



Ejemplo simple de escaping quotes in shell:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

Se hace terminando uno ya abierto ('), colocando escapado uno (\'), luego abriendo otro (') Esta sintaxis funciona para todos los comandos. Es un enfoque muy similar a la primera respuesta.


14
2018-02-28 20:59



No estoy abordando específicamente el tema de las citas porque, bueno, a veces, es razonable considerar un enfoque alternativo.

rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }

que puedes llamar como:

rxvt 123456 654321

la idea es que ahora puede alias esto sin preocuparse por las comillas:

alias rxvt='rxvt 123456 654321'

o, si necesita incluir el # en todas las llamadas por alguna razón:

rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }

que puedes llamar como:

rxvt '#123456' '#654321'

entonces, por supuesto, un alias es:

alias rxvt="rxvt '#123456' '#654321'"

(Ups, supongo que me dirigí a las citas :)


11
2017-08-22 04:59



Solo uso códigos de shell ... p. \x27 o \\x22 según corresponda Sin problemas, nunca realmente.


10
2017-12-16 16:15