una - ¿Cómo escapo del carácter comodín/asterisco en bash?
reemplazar caracteres bash (6)
p.ej.
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
y usando el caracter de escape "/":
me$ FOO="BAR /* BAR"
me$ echo $FOO
BAR /* BAR
Obviamente estoy haciendo algo estúpido.
¿Cómo obtengo la salida "BAR * BAR"?
Añadiré un poco a este viejo hilo.
Usualmente usarías
$ echo "$FOO"
Sin embargo, he tenido problemas incluso con esta sintaxis. Considere la siguiente secuencia de comandos.
#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"
El *
debe pasar literalmente para curl
, pero surgirán los mismos problemas. El ejemplo anterior no funcionará (se expandirá a nombres de archivo en el directorio actual) y tampoco lo hará /*
. Tampoco puede citar $curl_opts
porque se reconocerá como una opción única (no válida) para curl
.
curl: option -s --noproxy * -O: is unknown
curl: try ''curl --help'' or ''curl --manual'' for more information
Por lo tanto, recomendaría el uso de la variable bash
$GLOBIGNORE
para evitar la expansión del nombre del archivo si se aplica al patrón global, o usar el indicador set -f
incorporado.
#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1" ## no filename expansion
Aplicando a su ejemplo original:
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
me$ set -f
me$ echo $FOO
BAR * BAR
me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR
Citar cuando se establece $ FOO no es suficiente. También debe citar la referencia de la variable:
me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR
Puede valer la pena adquirir el hábito de usar printf
lugar de echo
en la línea de comando.
En este ejemplo, no ofrece muchos beneficios, pero puede ser más útil con resultados más complejos.
FOO="BAR * BAR"
printf %s "$FOO"
RESPUESTA CORTA
Como han dicho otros, siempre debe citar las variables para evitar comportamientos extraños. Entonces use echo "$ foo" en lugar de solo echo $ foo .
RESPUESTA LARGA
Creo que este ejemplo merece una explicación más amplia porque hay más cosas de las que podría parecer a primera vista.
Puedo ver dónde entra tu confusión porque después de ejecutar tu primer ejemplo, probablemente pensaste que el caparazón obviamente lo está haciendo:
- Expansión de parámetros
- Extensión de nombre de archivo
Entonces desde tu primer ejemplo:
me$ FOO="BAR * BAR"
me$ echo $FOO
Después de la expansión del parámetro es equivalente a:
me$ echo BAR * BAR
Y después de la expansión del nombre de archivo es equivalente a:
me$ echo BAR file1 file2 file3 file4 BAR
Y si simplemente escribes echo BAR * BAR
en la línea de comando, verás que son equivalentes.
Así que probablemente pensó "si escapo *, puedo evitar la expansión del nombre de archivo"
Entonces desde tu segundo ejemplo:
me$ FOO="BAR /* BAR"
me$ echo $FOO
Después de la expansión del parámetro debe ser equivalente a:
me$ echo BAR /* BAR
Y después de la expansión del nombre de archivo debe ser equivalente a:
me$ echo BAR /* BAR
Y si intenta escribir "echo BAR / * BAR" directamente en la línea de comando, imprimirá "BAR * BAR" porque el escape evita la expansión del nombre de archivo.
Entonces, ¿por qué usar $ foo no funciona?
Es porque hay una tercera expansión que tiene lugar: Quitar eliminación. De la eliminación manual de citas bash es:
Después de las expansiones anteriores, se eliminan todas las apariciones sin comillas de los caracteres ''/', '''' ''y'' "''que no resultaron de una de las expansiones anteriores.
Entonces, ¿qué ocurre cuando escribes el comando directamente en la línea de comando, el carácter de escape no es el resultado de una expansión previa, entonces BASH lo elimina antes de enviarlo al comando echo, pero en el segundo ejemplo, el "/ *" era el resultado de una expansión de parámetro anterior, por lo que NO se elimina. Como resultado, el eco recibe "/ *" y eso es lo que imprime.
Tenga en cuenta la diferencia entre el primer ejemplo - "*" no está incluido en los caracteres que se eliminarán mediante Quote Removal.
Espero que esto tenga sentido. Al final la conclusión es la misma: solo use comillas. Solo pensé en explicar por qué el escape, que lógicamente debería funcionar si solo están en juego la expansión de parámetros y nombres de archivo, no funcionó.
Para una explicación completa de las expansiones de BASH, consulte:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
FOO=''BAR * BAR''
echo "$FOO"
echo "$FOO"