Question

par exemple.

me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR

et en utilisant le " \ " caractère d'échappement:

me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR

Je fais évidemment quelque chose de stupide.

Comment puis-je obtenir le résultat "BAR * BAR"? ?

Était-ce utile?

La solution

Citer lorsque le paramètre $ FOO n'est pas suffisant. Vous devez également citer la référence de la variable:

me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR

Autres conseils

RÉPONSE COURTE

Comme d’autres l’ont dit, vous devez toujours citer les variables pour éviter tout comportement étrange. Utilisez donc echo "$ foo" dans au lieu de echo $ foo .

REPONSE LONGUE

Je pense vraiment que cet exemple mérite une explication supplémentaire, car il se passe plus de choses qu'il n'y paraît à première vue.

Je peux voir d'où vient votre confusion, car après avoir donné votre premier exemple, vous vous êtes probablement dit que le shell était en train de le faire:

  1. expansion des paramètres
  2. extension du nom de fichier

Donc, à partir de votre premier exemple:

me$ FOO="BAR * BAR"
me$ echo $FOO

Après l’extension du paramètre est équivalent à:

me$ echo BAR * BAR

Et après l'extension du nom de fichier é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.

Vous avez donc probablement pensé "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 le développement des paramètres doit être équivalent à:

me$ echo BAR \* BAR

Et après l'extension du nom de fichier doit être équivalent à:

<*>

Et si vous essayez de saisir "echo BAR \ * BAR" directement dans la ligne de commande, il imprimera bien " BAR * BAR " car l'expansion du nom de fichier est empêchée par l'échappement.

Alors pourquoi utiliser $ foo ne fonctionne pas?

C’est parce qu’une troisième expansion a lieu: la suppression des devis. La suppression manuelle des devis de bash est la suivante:

  

Après les extensions précédentes, tous   occurrences non citées des personnages   & # 8216; \ & # 8217 ;, & # 8216; '& # 8217 ;, & # 8216; " & 8217; cela n'a pas abouti   de l'une des extensions ci-dessus sont   supprimé.

Ainsi, lorsque vous tapez la commande directement dans la ligne de commande, le caractère d'échappement n'est pas le résultat d'une précédente expansion. BASH le supprime avant de l'envoyer à la commande echo, mais dans le deuxième exemple, le signe " \ * " était le résultat d'une précédente expansion de paramètre, elle n'est donc PAS supprimée. En conséquence, l’écho reçoit " \ * " et c’est ce qui est imprimé.

Notez la différence entre le premier exemple - " * " n'est pas inclus dans les caractères qui seront supprimés par la suppression des devis.

J'espère que cela a du sens. En fin de compte la conclusion dans le même - il suffit d'utiliser des guillemets. Je pensais juste que j’expliquerais pourquoi s’échapper, ce qui devrait logiquement fonctionner si seulement le développement des paramètres et des noms de fichiers sont en jeu ne fonctionne 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 à cet ancien fil de discussion.

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"

Le * doit être transmis intégralement à curl , mais les mêmes problèmes se poseront. L'exemple ci-dessus ne fonctionnera pas (les noms de fichiers du répertoire en cours seront étendus) et \ * non plus. Vous ne pouvez pas non plus citer $ curl_opts car il sera reconnu comme une option unique (non valide) pour 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 variable bash $ GLOBIGNORE pour empêcher l'expansion du nom de fichier si elle était appliquée au modèle global, ou utilisez le set -f indicateur intégré.

#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"  ## no filename expansion

Application à 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
FOO='BAR * BAR'
echo "$FOO"
echo "$FOO"

Il peut être intéressant de prendre l'habitude d'utiliser printf plutôt que echo sur la ligne de commande.

Dans cet exemple, cela ne présente pas beaucoup d'avantages, mais cela peut être plus utile avec des sorties plus complexes.

FOO="BAR * BAR"
printf %s "$FOO"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top