bash - usar - ¿Cómo escapar de comillas simples dentro de cadenas entre comillas simples?
poner comillas en un string php (19)
Ambas versiones funcionan, ya sea con concatenación utilizando el carácter de comillas simples escapadas (/ ''), o con concatenación al encerrar el carácter de comillas simples entre comillas dobles ("''").
El autor de la pregunta no se dio cuenta de que había una sola cita adicional ('') al final de su último intento de fuga:
alias rxvt=''urxvt -fg''/'''#111111''/''' -bg ''/'''#111111''/'''
│ │┊┊| │┊┊│ │┊┊│ │┊┊│
└─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
┊┊ ┊┊ ┊┊ ┊┊│
┊┊ ┊┊ ┊┊ ┊┊│
└┴─────────┴┴───┰───┴┴─────────┴┘│
All escaped single quotes │
│
?
Como puede ver en la bonita pieza anterior de ASCII / Unicode art, a la última comilla simple escapada (/ '') le sigue una comilla simple ('') innecesaria. Usar un resaltador de sintaxis como el que se encuentra en Notepad ++ puede resultar muy útil.
Lo mismo es cierto para otro ejemplo como el siguiente:
alias rc=''sed ''"''"'':a;N;$!ba;s//n/, /g''"''"
alias rc=''sed ''/''':a;N;$!ba;s//n/, /g''/'
Estos dos hermosos ejemplos de alias muestran de una manera muy intrincada y confusa cómo se puede alinear un archivo. Es decir, de un archivo con muchas líneas solo se obtiene una línea con comas y espacios entre los contenidos de las líneas anteriores. Para dar sentido al comentario anterior, el siguiente es un ejemplo:
$ cat Little_Commas.TXT
201737194
201802699
201835214
$ rc Little_Commas.TXT
201737194, 201802699, 201835214
Digamos que tienes un alias
bash 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 emparejando 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 desagradable, aunque representaría la misma cadena si se le permitiera concatenarlos de esa manera.
Aquí hay otra solución. Esta función tomará un solo argumento y lo citará apropiadamente usando el carácter de comilla simple, tal como lo explica la respuesta votada anteriormente:
single_quote() {
local quoted="''"
local i=0
while [ $i -lt ${#1} ]; do
local ch="${1:i:1}"
if [[ "$ch" != "''" ]]; then
quoted="$quoted$ch"
else
local single_quotes="''"
local j=1
while [ $j -lt ${#1} ] && [[ "${1:i+j:1}" == "''" ]]; do
single_quotes="$single_quotes''"
((j++))
done
quoted="$quoted''/"$single_quotes/"''"
((i+=j-1))
fi
((i++))
done
echo "$quoted''"
}
Entonces, puedes usarlo de esta manera:
single_quote "1 2 ''3''"
''1 2 ''"''"''3''"''"''''
x="this text is quoted: ''hello''"
eval "echo $(single_quote "$x")"
this text is quoted: ''hello''
Aquí hay una explicación sobre la única respuesta verdadera mencionada anteriormente:
A veces descargaré usando rsync sobre ssh y tendré que escapar de un nombre de archivo con un ''¡DOS VECES! (OMG!) Una vez para bash y una vez para ssh. El mismo principio de alternar delimitadores de citas está en funcionamiento aquí.
Por ejemplo, digamos que queremos obtener: Historias de Los Angeles de Louis Theroux ...
- Primero debe incluir a Louis Theroux en comillas simples para bash y comillas dobles para ssh: ''"Louis Theroux"''
- Luego usas comillas simples para escapar de una comilla doble "" ''
- El uso de comillas dobles para escapar del apóstrofe "''"
- Luego repita # 2, usando comillas simples para escapar de una comilla doble "" ''
- Luego, incluya LA Stories entre comillas simples para bash y comillas dobles para ssh: ''"LA Stories"''
Y he aquí! Usted termina con esto:
rsync -ave ssh ''"Louis Theroux"''''"''"''"''"''''"s LA Stories"''
que es un montón de trabajo para un pequeño ''- pero ahí va
Dado que Bash 2.04 syntax $''string''
(en lugar de solo ''string''
; aviso: no confundir con $(''string'')
) es otro mecanismo de citación que permite secuencias de escape similares a ANSI C y realiza la expansión a una versión de comillas simples.
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 espera:
/' single quote
/" double quote
// backslash
/n new line
/t horizontal tab
/r carriage return
A continuación se muestra la documentación relacionada copia y pegada de man bash
(versión 4.4):
Las palabras de la forma $ ''cadena'' se tratan especialmente. La palabra se expande a la cadena, con caracteres de escape de 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 expandido es de una sola cita, como si el signo de dólar no hubiera estado presente.
Consulte Citas y escapadas: a ANSI C le gustan las cadenas en la wiki de bash-hackers.org para obtener más detalles. También tenga en cuenta que el archivo "Bash Changes" ( 2.04 ) menciona mucho los cambios y correcciones de errores relacionados con el mecanismo de cotización $''string''
.
Según unix.stackexchange.com ¿Cómo usar un carácter especial como uno normal? debería funcionar (con algunas variaciones) en bash, zsh, mksh, ksh93 y FreeBSD y busybox sh.
Ejemplo simple de comillas de escape en shell:
$ echo ''abc''/'''abc''
abc''abc
$ echo "abc"/""abc"
abc"abc
Se hace al terminar ya abierto uno ( ''
), colocando uno escapado ( /'
), luego abriendo otro ( ''
). Esta sintaxis funciona para todos los comandos. Es un enfoque muy similar a la primera respuesta.
En el ejemplo dado, simplemente usamos comillas dobles en lugar de comillas simples como mecanismo de escape externo:
alias rxvt="urxvt -fg ''#111111'' -bg ''#111111''"
Este enfoque es adecuado para muchos casos en los que solo desea pasar una cadena fija a un comando: simplemente verifique cómo interpretará el shell la cadena entre comillas dobles a través de un echo
, y escape los caracteres con una barra invertida si es necesario.
En el ejemplo, verías que las comillas dobles son suficientes para proteger la cadena:
$ echo "urxvt -fg ''#111111'' -bg ''#111111''"
urxvt -fg ''#111111'' -bg ''#111111''
En mi humilde opinión, la respuesta real es que no puede escapar de comillas simples dentro de cadenas de comillas simples.
Es imposible.
Si suponemos que estamos usando bash.
Desde el manual de bash ...
Enclosing characters in single quotes preserves the literal value of each
character within the quotes. A single quote may not occur
between single quotes, even when preceded by a backslash.
Debe usar uno de los otros mecanismos de escape de cadenas "o /
No hay nada mágico en el alias
que exige que use comillas simples.
Tanto los siguientes trabajos en bash.
alias rxvt="urxvt -fg ''#111111'' -bg ''#111111''"
alias rxvt=urxvt/ -fg/ /'#111111/'/ -bg/ /'#111111/'
Este último está usando / para escapar del carácter de espacio.
Tampoco hay nada mágico en # 111111 que requiera comillas simples.
Las siguientes opciones logran el mismo resultado que las otras dos opciones, en que el alias de rxvt funciona como se esperaba.
alias rxvt=''urxvt -fg "#111111" -bg "#111111"''
alias rxvt="urxvt -fg /"#111111/" -bg /"#111111/""
También puedes escapar del # problemático directamente
alias rxvt="urxvt -fg /#111111 -bg /#111111"
Esta función:
quote ()
{
local quoted=${1///'//'///'/'};
printf "''%s''" "$quoted"
}
Permite citar de ''
adentro ''
. Utilice como esto:
$ quote "urxvt -fg ''#111111'' -bg ''#111111''"
''urxvt -fg ''/'''#111111''/''' -bg ''/'''#111111''/'''''
Si la línea a citar se vuelve más compleja, como las comillas dobles mezcladas con comillas simples, puede ser bastante difícil conseguir que la cadena cite dentro de una variable. Cuando aparezcan estos casos, escriba la línea exacta que necesita citar dentro de un script (similar a esto).
#!/bin/bash
quote ()
{
local quoted=${1///'//'///'/'};
printf "''%s''" "$quoted"
}
while read line; do
quote "$line"
done <<-/_lines_to_quote_
urxvt -fg ''#111111'' -bg ''#111111''
Louis Theroux''s LA Stories
''single quote phrase'' "double quote phrase"
_lines_to_quote_
Saldrá:
''urxvt -fg ''/'''#111111''/''' -bg ''/'''#111111''/'''''
''Louis Theroux''/'''s LA Stories''
''''/'''single quote phrase''/''' "double quote phrase"''
Todas las cadenas correctamente citadas dentro de comillas simples.
La mayoría de estas respuestas se refieren al caso específico sobre el que estás preguntando. Hay un enfoque general que un amigo y yo hemos desarrollado que permite una cita arbitraria en caso de que necesite citar los comandos de bash a través de múltiples capas de expansión de shell, por ejemplo, a través de ssh, su -c
, bash -c
, etc. núcleo primitivo que necesitas, aquí en bash nativo:
quote_args() {
local sq="''"
local dq=''"''
local space=""
local arg
for arg; do
echo -n "$space''${arg//$sq/$sq$dq$sq$dq$sq}''"
space=" "
done
}
Esto hace exactamente lo que dice: incluye cada argumento de forma individual (después de la expansión de bash, por supuesto):
$ quote_args foo bar
''foo'' ''bar''
$ quote_args arg1 ''arg2 arg2a'' arg3
''arg1'' ''arg2 arg2a'' ''arg3''
$ quote_args dq''"''
''dq"''
$ quote_args dq''"'' sq"''"
''dq"'' ''sq''"''"''''
$ quote_args "*"
''*''
$ quote_args /b*
''/bin'' ''/boot''
Hace lo obvio para una capa de expansión:
$ bash -c "$(quote_args echo a''"''b"''"c arg2)"
a"b''c arg2
(Tenga en cuenta que las comillas dobles alrededor de $(quote_args ...)
son necesarias para convertir el resultado en un solo argumento para bash -c
.) Y se puede usar de manera más general para citar correctamente a través de múltiples capas de expansión:
$ bash -c "$(quote_args bash -c "$(quote_args echo a''"''b"''"c arg2)")"
a"b''c arg2
El ejemplo anterior:
- shell-quotes cada argumento para el
quote_args
interno individualmente y luego combina la salida resultante en un solo argumento con las comillas dobles internas. - shell-quotes
bash
,-c
y el resultado ya citado una vez del paso 1, y luego combina el resultado en un solo argumento con las comillas dobles externas. - envía ese lío como argumento al
bash -c
externobash -c
.
Esa es la idea en pocas palabras. Puede hacer algunas cosas bastante complicadas con esto, pero debe tener cuidado con el orden de evaluación y con qué subcadenas se citan. Por ejemplo, lo siguiente hace las cosas incorrectas (para alguna definición de "incorrecto"):
$ (cd /tmp; bash -c "$(quote_args cd /; pwd 1>&2)")
/tmp
$ (cd /tmp; bash -c "$(quote_args cd /; [ -e *sbin ] && echo success 1>&2 || echo failure 1>&2)")
failure
En el primer ejemplo, bash expande inmediatamente quote_args cd /; pwd 1>&2
quote_args cd /; pwd 1>&2
en dos comandos separados, quote_args cd /
y pwd 1>&2
, por lo que CWD sigue siendo /tmp
cuando se ejecuta el comando pwd
. El segundo ejemplo ilustra un problema similar para el globbing. De hecho, el mismo problema básico ocurre con todas las expansiones de bash. El problema aquí es que la sustitución de un comando no es una llamada a una función: está literalmente evaluando un script bash y utilizando su salida como parte de otro script bash.
Si intenta simplemente escapar de los operadores de shell, fallará porque la cadena resultante que se pasa a bash -c
es solo una secuencia de cadenas entre comillas individuales que luego no se interpretan como operadores, lo que es fácil de ver si se hace eco de la cadena que se habría pasado a bash:
$ (cd /tmp; echo "$(quote_args cd //; pwd 1/>/&2)")
''cd'' ''/;'' ''pwd'' ''1>&2''
$ (cd /tmp; echo "$(quote_args cd //; /[ -e /*sbin /] /&/& echo success 1/>/&2 /|/| echo failure 1/>/&2)")
''cd'' ''/;'' ''['' ''-e'' ''*sbin'' '']'' ''&&'' ''echo'' ''success'' ''1>&2'' ''||'' ''echo'' ''failure'' ''1>&2''
El problema aquí es que estás sobre-cotizando. Lo que necesita es que los operadores no tengan comillas como entrada para la envolvente bash -c
, lo que significa que deben estar fuera de la sustitución del comando $(quote_args ...)
.
En consecuencia, lo que debe hacer en el sentido más general es citar entre comillas cada palabra del comando que no se pretende expandir en el momento de la sustitución del comando por separado, y no aplicar ninguna cotización adicional a los operadores de shell:
$ (cd /tmp; echo "$(quote_args cd /); $(quote_args pwd) 1>&2")
''cd'' ''/''; ''pwd'' 1>&2
$ (cd /tmp; bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")
/
$ (cd /tmp; echo "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
''cd'' ''/''; [ -e *''sbin'' ] && ''echo'' ''success'' 1>&2 || ''echo'' ''failure'' 1>&2
$ (cd /tmp; bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
success
Una vez que hayas hecho esto, la cadena completa es un juego justo para citar más a niveles arbitrarios de evaluación:
$ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")"
/
$ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")"
/
$ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")")"
/
$ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")"
success
$ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *sbin ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")"
success
$ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")")"
success
etc.
Estos ejemplos pueden parecer exagerados dado que palabras como el success
, sbin
y pwd
no necesitan ser entre comillas, pero el punto clave que se debe recordar al escribir una secuencia de comandos es que desea citar todo lo que no es absolutamente necesario. seguro no necesita cotización, porque nunca se sabe cuándo un usuario lanzará un Robert''; rm -rf /
Robert''; rm -rf /
.
Para comprender mejor lo que sucede debajo de las sábanas, puedes jugar con dos funciones de ayuda pequeñas:
debug_args() {
for (( I=1; $I <= $#; I++ )); do
echo -n "$I:<${!I}> " 1>&2
done
echo 1>&2
}
debug_args_and_run() {
debug_args "$@"
"$@"
}
eso enumera cada argumento de un comando antes de ejecutarlo:
$ debug_args_and_run echo a''"''b"''"c arg2
1:<echo> 2:<a"b''c> 3:<arg2>
a"b''c arg2
$ bash -c "$(quote_args debug_args_and_run echo a''"''b"''"c arg2)"
1:<echo> 2:<a"b''c> 3:<arg2>
a"b''c arg2
$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a''"''b"''"c arg2)")"
1:<bash> 2:<-c> 3:<''debug_args_and_run'' ''echo'' ''a"b''"''"''c'' ''arg2''>
1:<echo> 2:<a"b''c> 3:<arg2>
a"b''c arg2
$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a''"''b"''"c arg2)")")"
1:<bash> 2:<-c> 3:<''debug_args_and_run'' ''bash'' ''-c'' ''''"''"''debug_args_and_run''"''"'' ''"''"''echo''"''"'' ''"''"''a"b''"''"''"''"''"''"''"''"''c''"''"'' ''"''"''arg2''"''"''''>
1:<bash> 2:<-c> 3:<''debug_args_and_run'' ''echo'' ''a"b''"''"''c'' ''arg2''>
1:<echo> 2:<a"b''c> 3:<arg2>
a"b''c arg2
$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a''"''b"''"c arg2)")")")"
1:<bash> 2:<-c> 3:<''debug_args_and_run'' ''bash'' ''-c'' ''''"''"''debug_args_and_run''"''"'' ''"''"''bash''"''"'' ''"''"''-c''"''"'' ''"''"''''"''"''"''"''"''"''"''"''debug_args_and_run''"''"''"''"''"''"''"''"'' ''"''"''"''"''"''"''"''"''echo''"''"''"''"''"''"''"''"'' ''"''"''"''"''"''"''"''"''a"b''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''"''c''"''"''"''"''"''"''"''"'' ''"''"''"''"''"''"''"''"''arg2''"''"''"''"''"''"''"''"''''"''"''''>
1:<bash> 2:<-c> 3:<''debug_args_and_run'' ''bash'' ''-c'' ''''"''"''debug_args_and_run''"''"'' ''"''"''echo''"''"'' ''"''"''a"b''"''"''"''"''"''"''"''"''c''"''"'' ''"''"''arg2''"''"''''>
1:<bash> 2:<-c> 3:<''debug_args_and_run'' ''echo'' ''a"b''"''"''c'' ''arg2''>
1:<echo> 2:<a"b''c> 3:<arg2>
a"b''c arg2
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 luego puedes llamar como:
rxvt 123456 654321
La idea es que ahora puede alias esto sin preocuparse por las citas:
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 luego puedes llamar como:
rxvt ''#123456'' ''#654321''
Entonces, por supuesto, un alias es:
alias rxvt="rxvt ''#123456'' ''#654321''"
(Uy, supongo que me dirijo a la cita :)
No veo la entrada en su blog (link pls?) Pero de acuerdo con el manual de referencia de la GNU :
Los caracteres que encierran entre comillas simples ('''' '') conservan el valor literal de cada carácter dentro de las comillas. Una comilla simple puede no aparecer entre comillas simples, incluso cuando está precedida por una 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
Obviamente, sería más fácil simplemente rodear con comillas dobles, pero ¿cuál es el desafío en eso? Aquí está la respuesta usando solo comillas simples. Estoy usando una variable en lugar de un alias
por lo que es más fácil de imprimir como prueba, pero es lo mismo que usar un alias
.
$ rxvt=''urxvt -fg ''/'''#111111''/''' -bg ''/'''#111111''/'
$ echo $rxvt
urxvt -fg ''#111111'' -bg ''#111111''
Explicación
La clave es que puede cerrar la comilla simple y volver a abrirla tantas veces como desee. Por ejemplo, foo=''a''''b''
es lo mismo que foo=''ab''
. Por lo tanto, puede cerrar la comilla simple, agregar una comilla literal, y volver a abrir la siguiente comilla simple.
Diagrama de descomposición
Este diagrama lo aclara utilizando corchetes para mostrar dónde se abren y cierran las comillas simples. Las citas no están "anidadas" como pueden estar los paréntesis. También puede prestar atención al resaltado de color, que se aplica correctamente. Las cadenas citadas son marrón, mientras que el /'
es negro.
''urxvt -fg ''/'''#111111''/''' -bg ''/'''#111111''/' # original
[^^^^^^^^^^] ^[^^^^^^^] ^[^^^^^] ^[^^^^^^^] ^ # show open/close quotes
urxvt -fg '' #111111 '' -bg '' #111111 '' # literal characters remaining
(Esta es esencialmente la misma respuesta que la de Adrian, pero creo que esto lo explica mejor. Además, su respuesta tiene 2 comillas simples superfluas al final).
Puedo confirmar que el uso de ''/'''
para una comilla simple dentro de una cadena entre comillas simples funciona en Bash, y se puede explicar de la misma manera que el argumento "pegado" de la secuencia anterior. Supongamos que tenemos una cadena entre comillas: ''A ''/'''B''/''' C''
(todas las comillas aquí son comillas simples). Si se pasa a echo, imprime lo siguiente: A ''B'' C
En cada ''/'''
la primera comilla cierra la cadena actual entre comillas simples, la siguiente /'
pega una comilla simple a la cadena anterior ( /'
es una forma de especificar una comilla simple sin comenzar una cadena entre comillas), y la última quote abre otra cadena entre comillas simples.
Si está generando la cadena de shell en Python 2 o Python 3, lo siguiente puede ayudar a citar los argumentos:
#!/usr/bin/env python
from __future__ import print_function
try: # py3
from shlex import quote as shlex_quote
except ImportError: # py2
from pipes import quote as shlex_quote
s = """foo ain''t "bad" so there!"""
print(s)
print(" ".join([shlex_quote(t) for t in s.split()]))
Esto dará como resultado:
foo ain''t "bad" so there!
foo ''ain''"''"''t'' ''"bad"'' so ''there!''
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 ''"''"''
se interpreta como simplemente ''
:
-
''
Finalizar primera cita que utiliza comillas simples. -
"
Comience la segunda cita, utilizando comillas dobles. -
''
Personaje citado. -
"
Finalizar segunda cita, utilizando comillas dobles. -
''
Comience la tercera cita, utilizando comillas simples.
Si no coloca espacios en blanco entre (1) y (2), o entre (4) y (5), el shell interpretará esa cadena como una palabra larga.
Siempre simplemente sustituyo cada comilla simple incrustada con la secuencia: ''/'''
(es decir: quote backslash quote quote) que cierra la cadena, agrega una comilla simple escapada y vuelve a abrir la cadena.
A menudo hago una función de "cita" 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 introduces eval
en tus shell-scripts. ¡Esencialmente tienes que volver a cotizar todo de nuevo!
Por ejemplo, cree un script de Perl llamado quotify que contenga las declaraciones anteriores:
#!/usr/bin/perl -pl
s/''/''//'''/g;
$_ = qq[''$_''];
luego úselo para generar una cadena correctamente citada:
$ 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 el comando de nuevo:
$ quotify
alias rxvt=''urxvt -fg ''/'''#111111''/''' -bg ''/'''#111111''/'''''
resultado:
''alias rxvt=''/'''urxvt -fg ''/'''/'/'''''/'''#111111''/'''/'/'''''/''' -bg ''/'''/'/'''''/'''#111111''/'''/'/'''''/'''''/'''''
que se puede copiar / pegar en una eval:
eval ''alias rxvt=''/'''urxvt -fg ''/'''/'/'''''/'''#111111''/'''/'/'''''/''' -bg ''/'''/'/'''''/'''#111111''/'''/'/'''''/'''''/'''''
Solo uso códigos de shell ... por ejemplo, /x27
o //x22
según corresponda. Sin problemas, nunca realmente.
Ya que uno no puede poner comillas simples dentro de cadenas entre comillas simples, la opción más simple y más legible es usar una cadena HEREDOC
command=$(cat <<''COMMAND''
urxvt -fg ''#111111'' -bg ''#111111''
COMMAND
)
alias rxvt=$command
En el código anterior, el HEREDOC se envía al comando cat
y su salida se asigna a una variable a través de la notación de sustitución del comando $(..)
Es necesario poner una sola cita alrededor del HEREDOC ya que está dentro de $()
Otra forma de solucionar el problema de demasiadas capas de citas anidadas:
Está intentando abarrotar demasiado en un espacio demasiado pequeño, así que use una función de bash.
El problema es que está intentando tener demasiados niveles de anidamiento, y la tecnología de alias básica no es lo suficientemente potente como para adaptarse. Utilice una función de bash como esta para hacer que las comillas simples, las comillas dobles y los parámetros pasados se manejen normalmente, como es de esperar:
lets_do_some_stuff() {
tmp=$1 #keep a passed in parameter.
run_your_program $@ #use all your passed parameters.
echo -e ''/n-------------'' #use your single quotes.
echo `date` #use your back ticks.
echo -e "/n-------------" #use your double quotes.
}
alias foobarbaz=lets_do_some_stuff
Luego, puede usar sus variables de $ 1 y $ 2 y las comillas simples, dobles y pasadas atrás sin preocuparse de que la función de alias destruya su integridad.
Este programa imprime:
el@defiant ~/code $ foobarbaz alien Dyson ring detected @grid 10385
alien Dyson ring detected @grid 10385
-------------
Mon Oct 26 20:30:14 EDT 2015
-------------