¿Cómo escapar de las cotizaciones en shell?


66

Tengo problemas para escapar de personajes en bash. Me gustaría escapar de comillas simples y dobles mientras ejecuto un comando con un usuario diferente. A los fines de esta pregunta, digamos que quiero hacer eco de lo siguiente en la pantalla:

'single quote phrase' "double quote phrase"

¿Cómo puedo escapar de todos los caracteres especiales, si también necesito cambiar a un usuario diferente?

sudo su USER -c "echo \"'single quote phrase' \"double quote phrase\"\""

Por supuesto, esto no produce el resultado correcto.


+1 para "Por supuesto, esto no produce los resultados correctos". bashestá en camino de hacerme enojar.
Rolf

Respuestas:


89

Puede usar la siguiente sintaxis literal de cadena:

> echo $'\'single quote phrase\' "double quote phrase"'
'single quote phrase' "double quote phrase"

De man bash

Las palabras de la forma $ 'string' se tratan especialmente. La palabra se expande a cadena, con los caracteres 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
          \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)
          \cx    a control-x character

55
Exceso En la mayoría de los casos, no necesita usar la sintaxis literal de cadena.
fpmurphy


12

En un shell POSIX, suponiendo que en su cadena no haya expansión de variables, comandos o historial, y no haya nueva línea, siga estas prescripciones básicas:

  1. Para citar una cadena genérica con comillas simples, realice las siguientes acciones:

    1. Sustituya cualquier secuencia de caracteres sin comillas simples con la misma secuencia con comillas simples iniciales y finales agregadas: 'aaa' ==> ''aaa''

    2. Escape con una barra diagonal inversa cada carácter de comillas simples preexistentes : ' ==> \'
      en particular,''aaa'' ==> \''aaa'\'

  2. Para citar una cadena genérica con comillas dobles, realice las siguientes acciones:

    1. Agregue comillas dobles iniciales y finales: aaa ==> "aaa"

    2. Escape con una barra diagonal inversa cada carácter de comillas dobles y cada carácter de barra diagonal inversa: " ==> \", \ ==> \\

Un par de ejemplos:

''aaa""bbb''ccc\\ddd''  ==>  \'\''aaa""bbb'\'\''ccc\\ddd'\'\'
                        ==>  "''aaa\"\"bbb''ccc\\\\ddd''"

para que tu ejemplo se pueda expandir con lo siguiente:

#!/bin/sh

echo \''aaa'\'' "bbb"'
echo "'aaa' \"bbb\""

sudo su enzotib -c 'echo \'\'\''aaa'\''\'\'\'' "bbb"'\'
sudo su enzotib -c 'echo "'\''aaa'\'' \"bbb\""'

sudo su enzotib -c "echo \\''aaa'\\'' \"bbb\"'"
sudo su enzotib -c "echo \"'aaa' \\\"bbb\\\"\""

10

Ejemplo simple de comillas de escape en shell:

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

Se realiza al terminar uno abierto ( '), colocando uno escapado ( \') y luego abriendo otro ( ').

Alternativamente:

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

Se realiza al terminar uno ya abierto ( '), colocando una cita en otra cita ( "'") y luego abriendo otra ( ').

Relacionado: ¿Cómo escapar de comillas simples dentro de cadenas de comillas simples? en stackoverflow SE


1

La respuesta aceptada funciona para citas simples (un nivel):

$ echo $'\'single quote phrase\' "double quote phrase"'
'single quote phrase' "double quote phrase"

Para que el comando se presente al trabajo, debe citar dos veces.
Este script podría hacer todo el trabajo:

#!/bin/bash

quote () { 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

read -r line <<-\_line_to_quote_
'single quote phrase' "double quote phrase"
_line_to_quote_

quote "$line"; echo
quote "echo $(quote "$line")"; echo

Ejecute el script para obtener:

$ script
''\''single quote phrase'\'' "double quote phrase"'
'echo '\'''\''\'\'''\''single quote phrase'\''\'\'''\'' "double quote phrase"'\'''

La primera línea funciona para eco simple:

$ echo ''\''single quote phrase'\'' "double quote phrase"'
'single quote phrase' "double quote phrase"

La segunda línea funcionará para el comando entre comillas dobles:

sudo su USER -c 'echo '\'''\''\'\'''\''single quote phrase'\''\'\'''\'' "double quote phrase"'\'''

-3

echo 'Soy un estudiante' no funciona. Pero lo siguiente funciona:

echo $ 'Soy un estudiante' De la página de manual de bash:

Una comilla simple no puede aparecer entre comillas simples, incluso cuando está precedida por una barra diagonal inversa. .... Las palabras de la forma $ 'string' se tratan especialmente. La palabra se expande a cadena, con los caracteres con barra invertida reemplazados según lo especificado por el estándar ANSI C.


66
Esto no agrega nada a las respuestas existentes.
jasonwryan
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.