Quelle est la difference entre a[bc]d
et a{b,c}d
? Pourquoi les gens utilisent a{b,c}d
-ils quand il y en a déjà a[bc]d
?
ls
et que vous n'essayez que des caractères uniques, ils semblent fonctionner de la même manière.
Quelle est la difference entre a[bc]d
et a{b,c}d
? Pourquoi les gens utilisent a{b,c}d
-ils quand il y en a déjà a[bc]d
?
ls
et que vous n'essayez que des caractères uniques, ils semblent fonctionner de la même manière.
Réponses:
Les deux sont assez différents.
a[bc]d
est un modèle de nom de fichier (dans des shells autres que fish
). Il s'étendra aux deux noms de fichiers abd
et acd
s'il s'agit de noms de fichiers existants dans le répertoire en cours.
La [...]
partie est une expression entre crochets qui correspond à un seul caractère parmi ceux répertoriés (ou les éléments de classement lorsque des plages sont incluses). Pour faire correspondre le modèle a[bc]d
, le caractère entre les chaînes a
et d
dans un nom de fichier doit être a b
ou a c
.
S'il abd
existe, mais acd
n'existe pas, alors il ne ferait que s'étendre à abd
, et vice versa.
Si ni abd
, ni acd
exister, en fonction de la coquille et les options, il déclencherait une erreur (Unix d' origine sh
, (t)csh
, zsh
, fish
, bash -O failglob
) et peut - être sortir de la coquille, ou laisser le motif unexpanded¹ (Bourne-like et rc
-comme coquilles) ou étendre à rien ( bash/zsh/yash -o nullglob
, certaines anciennes versions de fish
, Unix d'origine sh
et (t)csh
s'il y a d'autres globs correspondants dans la même commande).
a{b,c}d
est une extension d'accolade (dans des coquilles qui les supportent). Il s'étendra aux deux chaînes abd
et acd
.
La {...}
pièce est un ensemble délimité par des virgules des chaînes (dans cet exemple, dans certains obus, il peut également être une plage telle que a..k
ou 20..25
ceux ou plus avancés comme 00..20..2
ou 0..20..2%02d
), et l'expansion est calculée en combinant chacun de ces chaînes avec le flanquante cordes a
et d
. Ces chaînes peuvent être plus longues qu'un seul caractère et peuvent également être des extensions d'accolade elles-mêmes.
L'expansion se produit indépendamment du fait que ces chaînes correspondent ou non aux noms de fichiers existants.
Si vous construisez des chaînes, utilisez une extension d'accolade. Si vous faites correspondre des noms de fichiers, utilisez un modèle de nom de fichier.
¹ Dans ce cas particulier, il a[bc]d
peut arriver que ce soit le nom d'un fichier existant, c'est pourquoi il est potentiellement dangereux d'utiliser des choses comme rm -f ./*.[ch]
celles-ci et rm -f ./*.{c,h}
c'est moins un problème.
a{b,c}d
, les parties b
et c
n'ont pas besoin d'être des lettres simples; par exemple ex{ten,ci}sion
. Alors que ex[tenci]sion
ou quoi que ce soit ne correspondra qu'à l' une de ces lettres.
a[bc]d
correspond au modèle et fait partie de la norme POSIX. Dans POSIX, ceci est introduit comme "expression de parenthèse de modèle". Il est documenté dans la section 2.13 du manuel
Lorsqu'ils ne sont pas entre guillemets et en dehors d'une expression entre crochets, les trois caractères suivants ont une signification particulière dans la spécification des modèles:
?
Un point d'interrogation est un modèle qui doit correspondre à n'importe quel caractère.
*Un astérisque est un modèle qui doit correspondre à plusieurs caractères, comme décrit dans Modèles correspondant à plusieurs caractères.
[La parenthèse ouverte doit introduire une expression de parenthèse de modèle.
La section 2.13.3 mentionne également quelque chose qui se comporte différemment de ce à quoi on pourrait s'attendre pour les expressions rationnelles habituelles quand il est utilisé pour l'expansion du nom de fichier (c'est moi qui souligne)
Les règles décrites jusqu'à présent dans Motifs correspondant à un seul caractère et Motifs correspondant à plusieurs caractères sont qualifiées par les règles suivantes qui s'appliquent lorsque la notation de correspondance de motifs est utilisée pour l'expansion du nom de fichier:
Le caractère barre oblique dans un nom de chemin doit être explicitement mis en correspondance en utilisant une ou plusieurs barres obliques dans le modèle; il ne doit correspondre ni à l'astérisque ni aux caractères spéciaux de point d'interrogation, ni à une expression entre crochets. Les barres obliques dans le modèle doivent être identifiées avant les expressions entre crochets; ainsi, une barre oblique ne peut pas être incluse dans une expression de crochet de modèle utilisée pour l'expansion du nom de fichier. Si un caractère barre oblique est trouvé après un caractère de crochet ouvert non échappé avant qu'un crochet carré de fermeture correspondant ne soit trouvé, le crochet ouvert doit être traité comme un caractère ordinaire. Par exemple, le modèle
"a[b/c]d"
ne correspond pas à des noms de chemin tels queabd
oua/d
. Il ne correspond qu'à un nom de chemin littéralementa[b/c]d
.
a{b,c}d
est l' expansion des accolades , ce n'est pas dans la spécification de POSIX. Voici la partie correspondante du manuel bash (souligné par moi):
L'expansion d'accolade est un mécanisme par lequel des chaînes arbitraires peuvent être générées. Ce mécanisme est similaire à l' extension de nom de fichier (voir Extension de nom de fichier), mais les noms de fichiers générés n'ont pas besoin d'exister . Les modèles à développer entre accolades prennent la forme d'un préambule facultatif , suivi soit d'une série de chaînes séparées par des virgules, soit d'une expression de séquence entre une paire d'accolades, suivie d'un post-scriptum facultatif . Le préambule est préfixé à chaque chaîne contenue dans les accolades, et le post-scriptum est ensuite ajouté à chaque chaîne résultante, s'étendant de gauche à droite.
Selon le commentaire de @mosvy, cela est apparu pour la première fois, csh
mais le comportement dans bash
est différent de csh
et d'autres coquilles. Ce type d'expansion de croisillons est également présent dans glob(3)
.
Il existe un autre type d'expansion d'accolades {a..z}
qui n'apparaît qu'après bash
3.0, et il y en a d'autres ajoutées dans bash
4.0.
Dans un shell où la globalisation est activée, exécutez dans un dossier vide, le résultat suivant est retourné
$ echo a[bc]d
a[bc]d
$ echo a{b,c}d
abd acd
En réponse au commentaire de @ Jesse_b, si vous êtes dans un shell interactif et que les deux s'appliquent, il a[bc]d
est moins difficile de taper. Par exemple grep pattern [ab][12].txt
.
csh
bien avant bash
. Il est également présent dans la fonction de bibliothèque glob (3). La différence est que dans bash
elle est effectuée avant les autres extensions: a=A; ab=A/B; ac=A/C; echo $a{b,c}
fonctionnera dans bash différemment de tout autre shell.
command a[bc]d
?