En Bash, al especificar argumentos de línea de comando para un comando, ¿qué caracteres se necesitan para escapar?
Están limitados a los meta-caracteres de Bash: espacio, ficha,
|
, &
, ;
, (
, )
, <
, y >
?
En Bash, al especificar argumentos de línea de comando para un comando, ¿qué caracteres se necesitan para escapar?
Están limitados a los meta-caracteres de Bash: espacio, ficha,
|
, &
, ;
, (
, )
, <
, y >
?
Respuestas:
Los siguientes caracteres tienen un significado especial para el shell en algunos contextos y es posible que se deban escapar en argumentos:
`
Backtick (U + 0060 Acento grave)~
Tilde (U + 007E)!
Signo de exclamación (U + 0021)#
Hash (U + 0023 Signo de número)$
Signo de dólar (U + 0024)&
Ampersand (U + 0026)*
Asterisco (U + 002A)(
Paréntesis izquierdo (U + 0028))
Paréntesis derecho (U + 0029)
( ⇥
) Pestaña (U + 0009){
Tirante izquierdo (U + 007B Soporte rizado izquierdo)[
Soporte cuadrado izquierdo (U + 005B)|
Barra vertical (línea vertical U + 007C)\
Backslash (U + 005C Solidus inversa);
Punto y coma (U + 003B)'
Presupuesto simple / Apostrophe (U + 0027)"
Comilla doble (U + 0022)↩
Nueva línea (U + 000A)<
Menos de (U + 003C)>
Mayor que (U + 003E)?
Signo de interrogación (U + 003F)
Espacio (U + 0020) 1Algunos de esos personajes se usan para más cosas y en más lugares que el que he vinculado.
Hay algunos casos de esquina que son explícitamente opcionales:
!
se puede deshabilitar con set +H
, que es el valor predeterminado en shells no interactivos.{
se puede deshabilitar con set +B
.*
y ?
se puede deshabilitar con set -f
oset -o noglob
.=
El signo igual (U + 003D) también debe escaparse si está habilitado set -k
o noset -o keyword
.Escapar de una nueva línea requiere una cita : las barras invertidas no harán el trabajo. Cualquier otro personaje listado en IFS necesitará un manejo similar. No necesita escapar ]
o }
, pero sí necesita escapar )
porque es un operador.
Algunos de estos personajes tienen límites más estrictos sobre cuándo realmente necesitan escapar que otros. Por ejemplo, a#b
está bien, pero a #b
es un comentario, aunque >
necesitaría escapar en ambos contextos. De todos modos, no está de más escapar de todos de forma conservadora, y es más fácil que recordar las distinciones.
Si el nombre del comando en sí es una palabra clave de shell ( if
, for
, do
), entonces tendrá que escapar o citar también. El único interesante de esos es in
, porque no es obvio que siempre es una palabra clave. Usted no necesita hacer eso por palabras clave utilizadas en los argumentos, sólo cuando se haya (tontos!) Nombró a un comando de uno de ellos. Operadores de Shell ( (
, &
, etc.) siempre necesitan citando a donde quiera que estén.
1 Stéphane ha notado que cualquier otro carácter en blanco de un solo byte de su localidad también necesita escapar. En los entornos locales más comunes y sensibles, al menos aquellos basados en C o UTF-8, son solo los caracteres de espacio en blanco anteriores. En algunas configuraciones regionales ISO-8859-1, el espacio sin interrupción U + 00A0 se considera en blanco, incluidos Solaris, los BSD y OS X (creo que es incorrecto). Si se trata de una configuración regional desconocida arbitraria, podría incluir casi cualquier cosa, incluidas letras, así que buena suerte.
Posiblemente, un solo byte considerado en blanco podría aparecer dentro de un carácter de varios bytes que no estaba en blanco, y no tendría forma de escapar de eso aparte de poner todo el asunto entre comillas. Esto no es una preocupación teórica: en un entorno local ISO-8859-1 desde arriba, ese A0
byte que se considera en blanco puede aparecer dentro de caracteres multibyte como UTF-8 codificado "à" ( C3 A0
). Para manejar esos caracteres de manera segura, deberá citarlos "à"
. Este comportamiento depende de la configuración regional en el entorno que ejecuta el script, no del lugar donde lo escribió.
Creo que este comportamiento se rompe de varias maneras, pero tenemos que jugar la mano que nos reparten. Si está trabajando con un conjunto de caracteres multibyte que no se sincroniza automáticamente, lo más seguro sería citar todo. Si estás en UTF-8 o C, estás a salvo (por el momento).
!
cuando la expansión del historial de csh está habilitada, generalmente no en scripts. [ ! -f a ]
o find . ! -name...
están bien Eso está cubierto por la sección de límites más estrictos, pero quizás valga la pena mencionarlo explícitamente.
hash[foo"]"]=
, ${var-foo"}"}
, [[ "!" = b ]]
, [[ a = "]]" ]]
, los operadores de expresiones regulares para [[ x =~ ".+[" ]]
. Otras palabras clave que {
( if
, while
, for
...) tendrían que ser citado para que no sean reconocidos como tales ...
]
), por lo que no los enumero. No creo que ninguna palabra clave necesite ser citada en la posición del argumento.
En GNU Parallel esto se prueba y se usa ampliamente:
$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
# quote newline as '\n'
$a =~ s/[\n]/'\n'/go;
Se ensayó en bash
, dash
, ash
, ksh
, zsh
, y fish
. Algunos de los personajes no necesitan comillas en algunas (versiones) de los shells, pero lo anterior funciona en todos los shells probados.
Si simplemente desea una cadena entre comillas, puede canalizarla en parallel --shellquote
:
printf "&*\t*!" | parallel --shellquote
Para una solución de escape ligera en Perl, estoy siguiendo el principio de comillas simples. Un Bash-string en comillas simples puede tener cualquier carácter, excepto la comilla simple en sí.
Mi código:
my $bash_reserved_characters_re = qr([ !"#$&'()*;<>?\[\\`{|~\t\n]);
while(<>) {
if (/$bash_reserved_characters_re/) {
my $quoted = s/'/'"'"'/gr;
print "'$quoted'";
} else {
print $_;
}
}
Ejemplo de ejecución 1:
$ echo -n "abc" | perl escape_bash_special_chars.pl
abc
Ejemplo de ejecución 2:
echo "abc" | perl escape_bash_special_chars.pl
'abc
'
Ejemplo de ejecución 3:
echo -n 'ab^c' | perl escape_bash_special_chars.pl
ab^c
Ejemplo de ejecución 4:
echo -n 'ab~c' | perl escape_bash_special_chars.pl
'ab~c'
Ejemplo de ejecución 5:
echo -n "ab'c" | perl escape_bash_special_chars.pl
'ab'"'"'c'
echo 'ab'"'"'c'
ab'c