Pourquoi est echo {1,2,3}étendu à 1 2 3, ce qui est un comportement attendu, tandis que echo [[:digit:]]revient [[:digit:]]alors que je m'attendais à ce qu'il imprime tous les chiffres de 0à 9?
Parce que ce sont deux choses différentes. Le {1,2,3}est un exemple d' expansion du corset . La {1,2,3}construction est développée par le shell , avant echomême de la voir. Vous pouvez voir ce qui se passe si vous utilisez set -x:
$ set-x
$ echo {1,2,3}+ echo 123123
Comme vous pouvez le voir, la commande echo {1,2,3}est étendue à:
echo 123
Cependant, [[:digit:]]est une classe de caractères POSIX . Lorsque vous le donnez echo, le shell le traite également en premier, mais cette fois, il est traité comme un glob de shell . cela fonctionne de la même manière que si vous exécutez echo *qui imprimera tous les fichiers du répertoire courant. Mais [[:digit:]]c'est un glob de shell qui correspondra à n'importe quel chiffre. Maintenant, en bash, si un glob de shell ne correspond à rien, il sera étendu à lui-même:
Si le glob correspond à quelque chose, cela sera imprimé:
$ echo /e*c
+ echo /etc
/etc
Dans les deux cas, echoimprime simplement ce que le shell lui dit d'imprimer, mais dans le second cas, puisque le glob correspond à quelque chose ( /etc), il est dit d'imprimer ce quelque chose.
Donc, comme vous n'avez pas de fichiers ou de répertoires dont le nom se compose exactement d'un chiffre (ce [[:digit:]]qui correspondrait), le glob est étendu à lui-même et vous obtenez:
$ echo [[:digit:]][[:digit:]]
Maintenant, essayez de créer un fichier appelé 5et d'exécuter la même commande:
$ echo [[:digit:]]5
Et s'il y a plus d'un fichier correspondant:
$ touch 15
$ echo [[:digit:]]15
Ceci est (en quelque sorte) documenté dans man bashl'explication des nullgloboptions qui désactive ce comportement:
nullglob
Ifset, bash allows patterns which match no files (see
PathnameExpansion above) to expand to a null string,
rather than themselves.
Voir aussi shopt -s failglobpour obtenir un comportement plus utile similaire à celui des coques modernes comme zshou fish.
Stéphane Chazelas
Je suis d'accord avec Stéphane, utilise failglob. nullglobpeut provoquer des problèmes inattendus, par exemple lors du collage d'une URL qui se trouve avoir un ?.
Kevin
1
Bien sûr, je n'ai mentionné que nullglobpour démontrer que le motif est interprété comme un glob par le shell.
terdon
14
{1,2,3}est l' expansion de l'accolade , elle s'étend aux mots énumérés sans égard à leur signification.
[...]est un groupe de caractères, utilisé dans l' expansion du nom de fichier (ou caractère générique ou glob) de manière similaire à l'astérisque *et au point d'interrogation ?. Il correspond à tout caractère unique figurant dans la liste ou aux caractères qui sont membres de groupes nommés, comme [:digit:]si ceux-ci sont répertoriés. Le comportement par défaut de la plupart des shells consiste à laisser le caractère générique tel quel s'il n'y a aucun fichier qui le corresponde.
(Notez que vous ne pouvez pas vraiment transformer un caractère générique / motif en l'ensemble de chaînes qu'il correspondrait. L'astérisque peut correspondre à n'importe quelle chaîne de n'importe quelle longueur, donc étendre n'importe quel modèle le contenant produirait une liste infinie de chaînes.)
Donc:
$ bash -c 'echo [[:digit:]]'# bash leaves it as-is[[:digit:]]
$ zsh -c 'echo [[:digit:]]'# zsh by default complains if no match
zsh:1: no matches found:[[:digit:]]
$ touch 13 d i g t
$ bash -c 'echo [[:digit:]]'# now there are two matches13# note that d, i, g and t do NOT match
Mais reste:
$ bash -c 'echo {1,2,3}'123
Les deux sont développés par le shell , peu importe si la commande que vous exécutez est ls, ou echoou rm. Notez également que si l'un d'eux est cité, ils ne seront pas développés:
$ bash -c 'echo "[[:digit:]]"'# even though matching files still exist[[:digit:]]
$ bash -c 'echo "{1,2,3}"'{1,2,3}
merci pour votre réponse, je suis nouveau sur linux alors permettez-moi de vous demander comment l'écho est lié aux fichiers 1 3, sa fonction est d'imprimer ses arguments à stdout ne recherchant pas de fichiers à ma connaissance
AbdAllah Talaat
1
@AbdAllahTalaat cela n'a rien à voir avec l'écho, en fait. Le shell (par exemple bash) "se développera" [[:digit:]]avant de le passer à echo, donc echone voit jamais [[:digit:]], il ne voit que 1 3. Vous pouvez le voir en action en exécutant set -xce qui affichera les commandes en cours d'exécution (exécutez-le set +xpour le désactiver à nouveau).
terdon
@AbdAllahTalaat, echone recherche pas de fichiers, le shell le fait, avant d'exécuter le echo.
ilkkachu
Surtout que je pense que sous DOS / Windows, les utilitaires développent les caractères génériques, pas le shell. (Je me trompe peut-être)
ilkkachu
désolé les gars j'ai changé la bonne réponse à la réponse de tedron parce que son commentaire contenait le sens que bash est ce que le travail ne fait pas écho ... sa réponse aussi contenait ce sens .. vous m'avez tous aidé ... je souhaitais si je pouvais mettre bonne réponse pour toutes vos réponses et commentaires
AbdAllah Talaat
4
{1,2,3}(et par exemple {1..3}sont des extensions d'accolade . Elles sont interprétées par le shell avant l'exécution de la commande.
[[:digit:]]est un jeton de correspondance de modèle , mais vous ne l'utilisez pas dans un emplacement contenant des fichiers correspondant à ce modèle. Si vous utilisez une correspondance de modèle qui n'a aucune correspondance, elle se développe à elle-même:
Réponses:
Parce que ce sont deux choses différentes. Le
{1,2,3}
est un exemple d' expansion du corset . La{1,2,3}
construction est développée par le shell , avantecho
même de la voir. Vous pouvez voir ce qui se passe si vous utilisezset -x
:Comme vous pouvez le voir, la commande
echo {1,2,3}
est étendue à:Cependant,
[[:digit:]]
est une classe de caractères POSIX . Lorsque vous le donnezecho
, le shell le traite également en premier, mais cette fois, il est traité comme un glob de shell . cela fonctionne de la même manière que si vous exécutezecho *
qui imprimera tous les fichiers du répertoire courant. Mais[[:digit:]]
c'est un glob de shell qui correspondra à n'importe quel chiffre. Maintenant, en bash, si un glob de shell ne correspond à rien, il sera étendu à lui-même:Si le glob correspond à quelque chose, cela sera imprimé:
Dans les deux cas,
echo
imprime simplement ce que le shell lui dit d'imprimer, mais dans le second cas, puisque le glob correspond à quelque chose (/etc
), il est dit d'imprimer ce quelque chose.Donc, comme vous n'avez pas de fichiers ou de répertoires dont le nom se compose exactement d'un chiffre (ce
[[:digit:]]
qui correspondrait), le glob est étendu à lui-même et vous obtenez:Maintenant, essayez de créer un fichier appelé
5
et d'exécuter la même commande:Et s'il y a plus d'un fichier correspondant:
Ceci est (en quelque sorte) documenté dans
man bash
l'explication desnullglob
options qui désactive ce comportement:Si vous définissez cette option:
la source
shopt -s failglob
pour obtenir un comportement plus utile similaire à celui des coques modernes commezsh
oufish
.failglob
.nullglob
peut provoquer des problèmes inattendus, par exemple lors du collage d'une URL qui se trouve avoir un?
.nullglob
pour démontrer que le motif est interprété comme un glob par le shell.{1,2,3}
est l' expansion de l'accolade , elle s'étend aux mots énumérés sans égard à leur signification.[...]
est un groupe de caractères, utilisé dans l' expansion du nom de fichier (ou caractère générique ou glob) de manière similaire à l'astérisque*
et au point d'interrogation?
. Il correspond à tout caractère unique figurant dans la liste ou aux caractères qui sont membres de groupes nommés, comme[:digit:]
si ceux-ci sont répertoriés. Le comportement par défaut de la plupart des shells consiste à laisser le caractère générique tel quel s'il n'y a aucun fichier qui le corresponde.(Notez que vous ne pouvez pas vraiment transformer un caractère générique / motif en l'ensemble de chaînes qu'il correspondrait. L'astérisque peut correspondre à n'importe quelle chaîne de n'importe quelle longueur, donc étendre n'importe quel modèle le contenant produirait une liste infinie de chaînes.)
Donc:
Mais reste:
Les deux sont développés par le shell , peu importe si la commande que vous exécutez est
ls
, ouecho
ourm
. Notez également que si l'un d'eux est cité, ils ne seront pas développés:la source
[[:digit:]]
avant de le passer àecho
, doncecho
ne voit jamais[[:digit:]]
, il ne voit que1 3
. Vous pouvez le voir en action en exécutantset -x
ce qui affichera les commandes en cours d'exécution (exécutez-leset +x
pour le désactiver à nouveau).echo
ne recherche pas de fichiers, le shell le fait, avant d'exécuter leecho
.{1,2,3}
(et par exemple{1..3}
sont des extensions d'accolade . Elles sont interprétées par le shell avant l'exécution de la commande.[[:digit:]]
est un jeton de correspondance de modèle , mais vous ne l'utilisez pas dans un emplacement contenant des fichiers correspondant à ce modèle. Si vous utilisez une correspondance de modèle qui n'a aucune correspondance, elle se développe à elle-même:la source