Réponses:
RÉPONSE COURTE
Comme d'autres l'ont dit, vous devez toujours citer les variables pour éviter un comportement étrange. Utilisez donc echo "$ foo" au lieu de simplement echo $ foo .
LONGUE RÉPONSE
Je pense que cet exemple mérite des explications supplémentaires, car il se passe plus qu'il n'y paraît à première vue.
Je peux voir d'où vient votre confusion, car après avoir exécuté votre premier exemple, vous vous êtes probablement dit que le shell faisait évidemment:
Donc à partir de votre premier exemple:
me$ FOO="BAR * BAR"
me$ echo $FOO
Après l'expansion des paramètres équivaut à:
me$ echo BAR * BAR
Et après l'extension du nom de fichier, cela équivaut à:
me$ echo BAR file1 file2 file3 file4 BAR
Et si vous tapez simplement echo BAR * BAR
dans la ligne de commande, vous verrez qu'ils sont équivalents.
Alors vous vous êtes probablement dit "si j'échappe au *, je peux empêcher l'expansion du nom de fichier"
Donc, à partir de votre deuxième exemple:
me$ FOO="BAR \* BAR"
me$ echo $FOO
Après l'expansion des paramètres doit être équivalent à:
me$ echo BAR \* BAR
Et après l'expansion du nom de fichier devrait être équivalent à:
me$ echo BAR \* BAR
Et si vous essayez de taper "echo BAR \ * BAR" directement dans la ligne de commande, cela affichera en effet "BAR * BAR" car l'expansion du nom de fichier est empêchée par l'échappement.
Alors pourquoi l'utilisation de $ foo n'a-t-elle pas fonctionné?
C'est parce qu'il y a une troisième extension qui a lieu - Quote Removal. De la suppression manuelle des devis bash est:
Après les extensions précédentes, toutes les occurrences sans guillemets des caractères '\', '' 'et' "'qui ne résultaient pas de l'une des extensions ci-dessus sont supprimées.
Donc ce qui se passe, c'est que lorsque vous tapez la commande directement dans la ligne de commande, le caractère d'échappement n'est pas le résultat d'une expansion précédente donc BASH le supprime avant de l'envoyer à la commande echo, mais dans le 2ème exemple, le "\ *" était le résultat d'une expansion de paramètre précédente, il n'est donc PAS supprimé. En conséquence, echo reçoit "\ *" et c'est ce qu'il imprime.
Notez la différence entre le premier exemple - "*" n'est pas inclus dans les caractères qui seront supprimés par la suppression de devis.
J'espère que cela a du sens. En fin de compte, la conclusion est la même - utilisez simplement des guillemets. J'ai juste pensé expliquer pourquoi échapper, ce qui devrait logiquement fonctionner si seules les extensions de paramètres et de noms de fichiers sont en jeu, ne fonctionnait pas.
Pour une explication complète des extensions BASH, reportez-vous à:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
Je vais ajouter un peu à ce vieux fil.
Habituellement, vous utiliseriez
$ echo "$FOO"
Cependant, j'ai eu des problèmes même avec cette syntaxe. Considérez le script suivant.
#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"
Les *
besoins doivent être transmis mot pour mot curl
, mais les mêmes problèmes se poseront. L'exemple ci-dessus ne fonctionnera pas (il s'étendra aux noms de fichiers dans le répertoire actuel) et ni l'un ni l'autre \*
. Vous ne pouvez pas non plus citer $curl_opts
car il sera reconnu comme une option unique (non valide) de curl
.
curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information
Par conséquent, je recommanderais l'utilisation de la bash
variable $GLOBIGNORE
pour empêcher complètement l'expansion du nom de fichier si elle est appliquée au modèle global, ou utilisez l' set -f
indicateur intégré.
#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1" ## no filename expansion
S'appliquant à votre exemple d'origine:
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
SELECT * FROM etc.
c'est la seule façon qui fonctionne.
FOO='BAR * BAR'
echo "$FOO"
echo "$FOO"
Il vaut peut-être la peine de prendre l'habitude d'utiliser printf
plutôt que echo
sur la ligne de commande.
Dans cet exemple, cela ne donne pas beaucoup d'avantages, mais cela peut être plus utile avec une sortie plus complexe.
FOO="BAR * BAR"
printf %s "$FOO"