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 de comillas?
alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
parece desgarbado, aunque representaría la misma cadena si se le permite concatenarlos así.
"\""
por lo que deben usarse con preferencia a la respuesta de @ liori siempre que sea posible.Respuestas:
Si realmente desea utilizar comillas simples en la capa más externa, recuerde que puede pegar ambos tipos de comillas. Ejemplo:
Explicación de cómo
'"'"'
se interpreta como justo'
:'
Termine la primera cita que usa comillas simples."
Comience la segunda cita, usando comillas dobles.'
Personaje citado"
Termine la segunda cita, usando comillas dobles.'
Comience la tercera cita, usando 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.
fuente
alias splitpath='echo $PATH | awk -F : '"'"'{print "PATH is set to"} {for (i=1;i<=NF;i++) {print "["i"]",$i}}'"'"
¡Funciona cuando hay comillas simples y comillas dobles en la cadena de alias!alias serve_this_dir='ruby -rrack -e "include Rack;Handler::Thin.run Builder.new{run Directory.new'"'"''"'"'}"'
'\''
es mucho más legible en la mayoría de los contextos que'"'"'
. De hecho, el primero es casi siempre claramente distinto dentro de una cadena entre comillas simples, y por lo tanto, es solo una cuestión de mapearlo semánticamente al significado de "es una comilla escapada", como se hace con\"
cadenas entre comillas dobles. Mientras que este último se combina en una línea de marcas de cotización y necesita una inspección cuidadosa en muchos casos para distinguir adecuadamente.Siempre reemplazo cada comilla simple incrustada con la secuencia:
'\''
(es decir: comilla de comilla invertida) que cierra la cadena, agrega una comilla simple escapada y vuelve a abrir la cadena.A menudo utilizo una función "cotizar" en mis scripts de Perl para hacer esto por mí. Los pasos serían:
Esto prácticamente se encarga de todos los casos.
La vida se vuelve más divertida cuando introduces
eval
tus scripts de shell. ¡Esencialmente tienes que volver a cotizar todo de nuevo!Por ejemplo, cree un script de Perl llamado quotify que contenga las declaraciones anteriores:
luego úselo para generar una cadena citada correctamente:
resultado:
que luego se puede copiar / pegar en el comando alias:
(Si necesita insertar el comando en una evaluación, ejecute la cita nuevamente:
resultado:
que se puede copiar / pegar en una evaluación:
fuente
set -x
yecho "here's a string"
verá que se ejecuta bashecho 'here'\''s a string'
. (set +x
para devolver el comportamiento normal)Dado que la sintaxis Bash 2.04
$'string'
(en lugar de solo'string'
; advertencia: no confundir con$('string')
) es otro mecanismo de comillas que permite secuencias de escape tipo ANSI C y se expande a la versión con comillas simples.Ejemplo simple:
En tu caso:
Las secuencias de escape comunes funcionan según lo esperado:
A continuación se muestra la documentación relacionada copia + pegada
man bash
(versión 4.4):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:
El resultado ampliado está entre comillas simples, como si el signo del dólar no hubiera estado presente.
Vea Citas y escapes: ANSI C como cadenas en el wiki de bash-hackers.org para más detalles. También tenga en cuenta que el archivo "Bash Changes" ( descripción general aquí ) menciona mucho los cambios y las correcciones de errores relacionados con el
$'string'
mecanismo de cotización.De acuerdo con unix.stackexchange.com ¿Cómo usar un carácter especial como normal? debería funcionar (con algunas variaciones) en bash, zsh, mksh, ksh93 y FreeBSD y busybox sh.
fuente
echo $'foo\'b!ar'
!ar': event not found
> echo $BASH_VERSION
4.2.47(1)-release
> echo $'foo\'b!ar'
foo'b!ar
$'
lo que probablemente la forma más fácil es probarlo usted mismo en sistemas más antiguos.e. Bash no longer inhibits C-style escape processing ($'...') while performing pattern substitution word expansions.
Tomado de tiswww.case.edu/php/chet/bash/CHANGES . Todavía funciona en 4.3.42 pero no en 4.3.48.No veo la entrada en su blog (¿enlace pls?) Pero según el manual de referencia de GNU :
entonces bash no entenderá:
alias x='y \'z '
sin embargo, puede hacer esto si lo rodea con comillas dobles:
fuente
Puedo confirmar que el uso
'\''
de una comilla simple dentro de una cadena entre comillas sí funciona en Bash, y se puede explicar de la misma manera que el argumento "pegar" 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 eco, imprime el siguiente:A 'B' C
. En cada una,'\''
la primera cita cierra la cadena de comillas simples actual, lo siguiente\'
pega una comilla simple a la cadena anterior (\'
es una forma de especificar una comilla simple sin comenzar una cadena de comillas), y la última comilla abre otra cadena de comillas simples.fuente
alias something='A '\''B'\'' C'
resulta ensomething
una sola cadena, por lo que, aunque el lado derecho de la tarea no es técnicamente una sola cadena, no creo que importe mucho.'A ' + ' + 'B' + ' + ' C'
. En otras palabras, una solución para insertar caracteres de comillas simples dentro de una cadena entre comillas simples debería permitirme crear dicha cadena por sí misma e imprimirla. Sin embargo, esta solución no funcionará en este caso.STR='\''; echo $STR
. Tal como se diseñó, BASH realmente no permite esto.'\''
funciona para bash. ¿Podría señalar qué secciones de gnu.org/software/bash/manual/bashref.html especifican tal comportamiento?Ambas versiones funcionan, ya sea con concatenación usando el carácter de comilla simple escapado (\ '), o con concatenación encerrando el carácter de comilla simple entre comillas dobles ("'").
El autor de la pregunta no se dio cuenta de que había una cita simple adicional (') al final de su último intento de fuga:
Como puede ver en la bonita pieza anterior de arte ASCII / Unicode, a la última comilla simple escapada (\ ') le sigue una comilla simple innecesaria ('). Usar un resaltador de sintaxis como el presente en Notepad ++ puede resultar muy útil.
Lo mismo es cierto para otro ejemplo como el siguiente:
Estas dos hermosas instancias de alias muestran de una manera muy intrincada y ofuscada 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 el contenido de las líneas anteriores. Para dar sentido al comentario anterior, el siguiente es un ejemplo:
fuente
Ejemplo simple de comillas de escape en shell:
Se realiza al terminar uno abierto (
'
), colocando uno escapado (\'
) y luego abriendo otro ('
). Esta sintaxis funciona para todos los comandos. Es un enfoque muy similar a la primera respuesta.fuente
No estoy abordando específicamente el problema de las citas porque, bueno, a veces, es razonable considerar un enfoque alternativo.
que luego puedes llamar como:
La idea es que ahora puede alias esto sin preocuparse por las comillas:
o, si necesita incluir el
#
en todas las llamadas por algún motivo:que luego puedes llamar como:
entonces, por supuesto, un alias es:
(Uy, supongo que me dirigí a la cita :)
fuente
Dado que no se pueden poner comillas simples dentro de cadenas entre comillas simples, la opción más simple y fácil de leer es usar una cadena HEREDOC
En el código anterior, el HEREDOC se envía al
cat
comando y su salida se asigna a una variable mediante la notación de sustitución del comando$(..)
Es necesario poner una cita simple alrededor del HEREDOC ya que está dentro de un
$()
fuente
dash
cuál es el shell predeterminado en los scripts de inicio de Ubuntu y en otros lugares.Solo uso códigos de shell ... por ejemplo,
\x27
o\\x22
según corresponda. Sin problemas, nunca realmente.fuente
x27
(en Centos 6.6)La mayoría de estas respuestas se refieren al caso específico que está preguntando. Hay un enfoque general que un amigo y yo hemos desarrollado que permite arbitraria citar en caso de que necesite cita fiesta de comandos a través de múltiples capas de desarrollo del forro, por ejemplo, a través de ssh,
su -c
,bash -c
, etc. Hay un núcleo primitivo que necesita, aquí en bash nativo:Esto hace exactamente lo que dice: cita cada argumento individualmente (después de la expansión bash, por supuesto):
Hace lo obvio para una capa de expansión:
(Tenga en cuenta que las comillas dobles
$(quote_args ...)
son necesarias para convertir el resultado en un argumento único parabash -c
). Y se puede usar de manera más general para citar correctamente a través de múltiples capas de expansión:El ejemplo anterior:
quote_args
individualmente y luego combina el resultado resultante en un solo argumento con las comillas dobles internas.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.bash -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 las subcadenas citadas. Por ejemplo, lo siguiente hace las cosas mal (para alguna definición de "mal"):
En el primer ejemplo, bash se expande inmediatamente
quote_args cd /; pwd 1>&2
en dos comandos separadosquote_args cd /
ypwd 1>&2
, por lo tanto, el CWD aún está en ejecución/tmp
cuandopwd
se ejecuta el comando. 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 una sustitución de comando no es una llamada a una función: literalmente está evaluando un script bash y usando 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
bash -c
es solo una secuencia de cadenas entre comillas individuales que no se interpretan como operadores, lo que es fácil de ver si repite la cadena que han pasado a bash:El problema aquí es que estás sobre citando. Lo que necesita es que los operadores no estén entre comillas como entrada para el cerramiento
bash -c
, lo que significa que deben estar fuera de la$(quote_args ...)
sustitución del comando.En consecuencia, lo que debe hacer en el sentido más general es citar shell cada palabra del comando que no se pretende expandir en el momento de la sustitución del comando por separado, y no aplicar ninguna cita adicional a los operadores de shell:
Una vez que haya hecho esto, toda la cadena es un juego justo para seguir citando a niveles arbitrarios de evaluación:
etc.
Estos ejemplos pueden parecer excesivos dado que las palabras como
success
,sbin
ypwd
no necesitan ser citadas, pero el punto clave a recordar cuando se escribe un script que toma una entrada arbitraria es que desea citar todo lo que no está absolutamente seguro . No es necesario citar, porque nunca se sabe cuándo un usuario arrojará aRobert'; rm -rf /
.Para comprender mejor lo que sucede debajo de las cubiertas, puedes jugar con dos pequeñas funciones auxiliares:
que enumerará cada argumento a un comando antes de ejecutarlo:
fuente
vagrant ssh -c {single-arg} guest
. Las{single-arg}
necesidades a ser tratados como un solo arg porque vagabundo toma el siguiente arg después de que el nombre del huésped. El orden no se puede cambiar. Pero necesitaba pasar un comando y sus argumentos dentro{single-arg}
. Por lo que utiliza suquote_args()
citar el comando y sus argumentos, y poner entre comillas el resultado, y funcionó como un encanto:vagrant ssh -c "'command' 'arg 1 with blanks' 'arg 2'" guest
. ¡¡¡Gracias!!!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.
Del manual bash ...
Debe usar uno de los otros mecanismos de escape de cadena "o \
No hay nada mágico
alias
que requiera el uso de comillas simples.Tanto el siguiente trabajo en bash.
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, ya que el alias rxvt funciona como se esperaba.
También puedes escapar del problemático # directamente
fuente
En el ejemplo dado, simplemente usó comillas dobles en lugar de comillas simples como mecanismo de escape externo:
Este enfoque es adecuado para muchos casos en los que solo desea pasar una cadena fija a un comando: solo verifique cómo el shell interpretará la cadena entre comillas dobles a través de un
echo
, y si es necesario, escape los caracteres con barra invertida.En el ejemplo, vería que las comillas dobles son suficientes para proteger la cadena:
fuente
Obviamente, sería más fácil simplemente rodearlo con comillas dobles, pero ¿dónde está el desafío en eso? Aquí está la respuesta usando solo comillas simples. Estoy usando una variable en lugar de,
alias
por lo que es más fácil imprimir como prueba, pero es lo mismo que usaralias
.Explicación
La clave es que puede cerrar la cotización simple y volver a abrirla tantas veces como desee. Por ejemplo
foo='a''b'
es lo mismo quefoo='ab'
. Por lo tanto, puede cerrar la comilla simple, incluir una comilla simple literal\'
y luego volver a abrir la siguiente.Diagrama de desglose
Este diagrama lo deja claro usando corchetes para mostrar dónde se abren y cierran las comillas simples. Las citas no están "anidadas" como pueden estar entre paréntesis. También puede prestar atención al resaltado de color, que se aplica correctamente. Las cadenas citadas son de color granate, mientras que el
\'
es de color negro.(Esta es esencialmente la misma respuesta que la de Adrian, pero creo que esto lo explica mejor. También su respuesta tiene 2 comillas simples superfluas al final).
fuente
'\''
método que recomiendo sobre el'"'"'
método que a menudo es más difícil de leer para los humanos.Aquí hay una elaboració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 otra para ssh. Aquí funciona el mismo principio de delimitadores de cotizaciones alternas.
Por ejemplo, digamos que queremos obtener: Historias de LA de Louis Theroux ...
Y he aquí! Terminas con esto:
que es mucho trabajo para un pequeño ', pero ahí lo tienes
fuente
Explicación de implementación:
comillas dobles para que podamos generar fácilmente comillas simples envolventes y usar la
${...}
sintaxisLa búsqueda y reemplazo de bash se ve así:
${varname//search/replacement}
estamos reemplazando
'
con'\''
'\''
codifica un solo'
así:'
termina la cita simple\'
codifica a'
(la barra invertida es necesaria porque no estamos entre comillas)'
comienza a cotizar de nuevobash concatena automáticamente cadenas sin espacios en blanco entre
hay un
\
antes de cada\
y'
porque esas son las reglas de escape${...//.../...}
.PS Siempre codifique para cadenas de comillas simples porque son mucho más simples que las cadenas de comillas dobles.
fuente
Otra forma de solucionar el problema de demasiadas capas de citas anidadas:
Estás tratando de meter demasiado en un espacio demasiado pequeño, así que usa una función 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 bash como esta para que las marcas simples, dobles y los parámetros pasados se manejen normalmente como se esperaría:
Luego puede usar sus variables de $ 1 y $ 2 y comillas simples, dobles y ticks sin preocuparse de que la función de alias destruya su integridad.
Este programa imprime:
fuente
Si tiene instalado GNU Parallel, puede usar su cita interna:
Desde la versión 20190222 puedes incluso
--shellquote
varias veces:Citará la cadena en todos los shells compatibles (no solo
bash
).fuente
Esta función:
Permite cotizar el
'
interior'
. Úselo así:Si la línea para citar se vuelve más compleja, como las comillas dobles mezcladas con comillas simples, puede ser bastante complicado hacer 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).
Saldrá:
Todas las cadenas correctamente citadas dentro de comillas simples.
fuente
Si está generando la cadena de shell dentro de Python 2 o Python 3, lo siguiente puede ayudar a citar los argumentos:
Esto generará:
fuente
Aquí están mis dos centavos, en el caso de que uno quiera ser
sh
portátil, no solobash
específico (sin embargo, la solución no es demasiado eficiente, ya que inicia un programa externosed
):quote.sh
(o simplementequote
) en algún lugar de tuPATH
:Un ejemplo:
Y, por supuesto, eso convierte de nuevo:
Explicación: básicamente tenemos que encerrar la entrada con comillas
'
, y luego reemplazar cualquier comilla simple con este micro-monstruo:'"'"'
(finalice la comilla de apertura con un emparejamiento'
, escape de la comilla simple encontrada envolviéndola con comillas dobles"'"
, y finalmente, emitir una nueva apertura comilla simple'
, o en seudo-notación:' + "'" + ' == '"'"'
)Una forma estándar de hacerlo sería utilizar
sed
el siguiente comando de sustitución:Sin embargo, un pequeño problema es que para usar eso en shell uno debe escapar de todos estos caracteres de comillas simples en la propia expresión sed, lo que lleva a algo así como
(y una buena manera de construir este resultado es alimentar la expresión original
s/\(['][']*\)/'"\1"'/g
a los guiones de Kyle Rose o George V. Reilly).Finalmente, tiene sentido esperar que la entrada provenga
stdin
, ya que pasarla por los argumentos de la línea de comandos ya podría ser un problema.(Ah, y es posible que queramos agregar un pequeño mensaje de ayuda para que el script no se cuelgue cuando alguien simplemente lo ejecuta y se
./quote.sh --help
pregunta qué hace).fuente
Aquí hay otra solución. Esta función tomará un argumento simple y lo citará apropiadamente usando el carácter de comillas simples, tal como lo explica la respuesta votada arriba:
Entonces, puedes usarlo de esta manera:
fuente