¿Hay alguna lista exhaustiva de caracteres que deben escaparse en Bash? ¿Se puede verificar solo con sed
?
En particular, estaba comprobando si %
es necesario escapar o no. Lo intenté
echo "h%h" | sed 's/%/i/g'
y funcionó bien, sin escapar %
. ¿Significa que %
no es necesario escapar? ¿Era esta una buena manera de verificar la necesidad?
Y más general: ¿son los mismos personajes para escapar shell
y bash
?
Respuestas:
Hay dos reglas fáciles y seguras que funcionan no solo en
sh
sino tambiénbash
.1. Ponga la cadena completa entre comillas simples
Esto funciona para todos los caracteres, excepto la comilla simple. Para escapar de la comilla simple, cierre la comilla anterior, inserte la comilla simple y vuelva a abrir la comilla.
comando sed:
sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
2. Escapar de cada personaje con una barra invertida
Esto funciona para todos los personajes, excepto para la nueva línea. Para los caracteres de nueva línea, utilice comillas simples o dobles. Las cadenas vacías aún deben manejarse; reemplácelas por
""
comando sed:
sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.2b. Versión más legible de 2
Hay un conjunto de caracteres fácil y seguro, como
[a-zA-Z0-9,._+:@%/-]
, que se puede dejar sin escape para que sea más legiblecomando sed:
LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.Tenga en cuenta que en un programa sed, uno no puede saber si la última línea de entrada termina con un byte de nueva línea (excepto cuando está vacío). Es por eso que los dos comandos anteriores suponen que no. Puede agregar una nueva línea entre comillas manualmente.
Tenga en cuenta que las variables de shell solo se definen para el texto en el sentido POSIX. El procesamiento de datos binarios no está definido. Para las implementaciones que importan, el binario funciona con la excepción de los bytes NUL (porque las variables se implementan con cadenas C y están destinadas a usarse como cadenas C, es decir, argumentos de programa), pero debe cambiar a una configuración regional "binaria" como latin1 .
(Puede validar fácilmente las reglas leyendo la especificación POSIX para
sh
. Para bash, consulte el manual de referencia vinculado por @AustinPhillips)fuente
sed
, pero sí requierebash
.formato que se puede reutilizar como entrada de shell
Hay una directiva de formato especial
printf
(%q
) creada para este tipo de solicitud:Algunas muestras:
Esto también podría usarse a través de variables:
Comprobación rápida con todos los (128) bytes ascii:
Tenga en cuenta que todos los bytes de 128 a 255 deben escaparse.
Esto debe representar algo como:
Donde el primer campo es el valor hexadecimal del byte, el segundo contiene
E
si el carácter necesita ser escapado y el tercer campo muestra la presentación del carácter escapado.Por qué
,
?Podrías ver algunos personajes que no siempre necesitan escapar, como
,
,}
y{
.Entonces no siempre pero algún momento :
o
pero cuidado:
fuente
subprocess.Popen(['bash', '-c', 'printf "%q\0" "$@"', '_', arbitrary_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()
le dará una versión correctamente citada de shellarbitrary_string
.%q
estuvo roto durante mucho tiempo: si mi mente me sirve bien, se solucionó un error (pero aún podría estar roto) en 2013 después de estar roto por ~ 10 años. Así que no confíes en ello.shlex.quote()
(> = 3.3,pipes.quote()
- indocumentado - para versiones anteriores) también hará el trabajo y producirá una versión más legible para los humanos (agregando comillas y escapando, según sea necesario) de la mayoría de las cadenas, sin la necesidad de generar una concha.,
. Me sorprendió saber que Bash incorporadoprintf -- %q ','
da\,
, pero/usr/bin/printf -- %q ','
da,
(sin escapar). Lo mismo para otros caracteres:{
,|
,}
,~
.Para salvar a alguien más de tener que usar RTFM ... en bash :
... así que si escapas de esos (y de la cita en sí misma, por supuesto) probablemente estés bien.
Si adopta un enfoque más conservador de 'en caso de duda, escape', debería ser posible evitar obtener caracteres con un significado especial al no escapar caracteres identificadores (es decir, letras ASCII, números o '_'). Es muy poco probable que estos (es decir, en algún extraño shell POSIX-ish) tengan un significado especial y, por lo tanto, necesiten escapar.
fuente
Usando la
print '%q'
técnica , podemos ejecutar un ciclo para descubrir qué caracteres son especiales:Da esta salida:
Algunos de los resultados, como
,
parecen un poco sospechosos. Sería interesante obtener las aportaciones de @ CharlesDuffy sobre esto.fuente
,
parecer un poco sospechoso en el último párrafo de mi respuesta%q
no sabe en qué parte del shell está planeando usar el personaje, por lo que escapará a todos los personajes que pueden tener un significado especial en cualquier contexto de shell posible.,
en sí misma no tiene un significado especial para ella, pero como @ F.Hauri ha señalado en su respuesta, sí tiene un significado especial dentro de la{...}
expansión de llaves : gnu.org/savannah-checkouts/gnu/bash/manual/… ¡ Esto es como! lo que también requiere expansión en situaciones específicas, no en general:echo Hello World!
funciona bien, peroecho test!test
fallará.Los caracteres que necesitan escapar son diferentes en Bourne o POSIX shell que Bash. Generalmente (muy) Bash es un superconjunto de esos proyectiles, por lo que todo lo que escapas
shell
debe escapar en Bash.Una buena regla general sería "en caso de duda, escapar de ella". Pero escapar de algunos personajes les da un significado especial, como
\n
. Estos se enumeran en lasman bash
páginas debajoQuoting
yecho
.Aparte de eso, escapa de cualquier personaje que no sea alfanumérico, es más seguro. No sé de una sola lista definitiva.
Las páginas del manual los enumeran a todos en alguna parte, pero no en un solo lugar. Aprende el idioma, esa es la manera de estar seguro.
Uno que me ha atrapado es
!
. Este es un personaje especial (expansión de la historia) en Bash (y csh) pero no en el shell Korn. Inclusoecho "Hello world!"
da problemas. El uso de comillas simples, como de costumbre, elimina el significado especial.fuente
sed
es lo suficientemente bueno para ver si tiene que escapar. ¡Gracias por tu respuesta!sed
No es necesario consultar, puedes consultar con casi cualquier cosa.sed
No es el problema,bash
es. Dentro de las comillas simples no hay caracteres especiales (excepto las comillas simples), ni siquiera puede escapar de los caracteres allí. Unsed
comando generalmente debe estar entre comillas simples porque los metacaracteres RE tienen demasiadas superposiciones con metacaracteres de shell para estar a salvo. La excepción es cuando se incrustan variables de shell, lo que debe hacerse con cuidado.echo
. Si saca lo que puso, no necesita escapar. :)Supongo que estás hablando de cuerdas de bash. Existen diferentes tipos de cadenas que tienen un conjunto diferente de requisitos para escapar. p.ej. Las cadenas de comillas simples son diferentes de las cadenas de comillas dobles.
La mejor referencia es el Citando sección del manual de bash.
Explica qué personajes necesitan escapar. Tenga en cuenta que algunos caracteres pueden necesitar escapar dependiendo de las opciones habilitadas, como la expansión del historial.
fuente
Me di cuenta de que bash escapa automáticamente a algunos caracteres cuando usa el autocompletado.
Por ejemplo, si tiene un directorio llamado
dir:A
, bash se completará automáticamente paradir\:A
Con esto, realicé algunos experimentos con caracteres de la tabla ASCII y obtuve las siguientes listas:
Caracteres que bash escapa en autocompletar : (incluye espacio)
Personajes que bash no escapa :
(Excluí
/
, ya que no se puede usar en los nombres de directorio)fuente
printf %q
modifica y qué no modifica si se pasa como argumento, idealmente, revisando todo el conjunto de caracteres.