J'ai remarqué que l' {
on peut utiliser pour l'expansion du corset:
echo {1..8}
ou en groupe de commandes:
{ls;echo hi}
Comment bash sait-il la différence?
bash
shell-script
source d'amour
la source
la source
{
interprété comme une liste de commandes s'il apparaît au début d'une commande et comme un développement d'accolade sinon, mais je ne suis pas sûr.{ls;echo hi}
n'est pas légalbash
. Vous avez besoin d'un espace après l'accolade d'ouverture et d'un point-virgule avant celui de clôture.Réponses:
Une raison simplifiée est l'existence d'un caractère: space.
Les développements d'accolades ne traitent pas les espaces (non cités).
Une
{...}
liste a besoin d'espaces (non cités).La réponse plus détaillée est la façon dont le shell analyse une ligne de commande .
La première étape pour analyser (comprendre) une ligne de commande consiste à la diviser en plusieurs parties.
Ces parties (généralement appelées mots ou jetons) résultent de la division d'une ligne de commande à chaque méta-caractère du lien :
Méta-personnages: spacetabenter;,<>|et &.
Après division, les mots peuvent être d'un type (tel que compris par la coque):
LC=ALL ...
LC=ALL echo
LC=ALL echo "hello"
LC=ALL echo "hello" >&2
Expansion de Brace
Si une "chaîne d'accolade" (sans espaces ni méta-caractères) est un mot unique (comme décrit ci-dessus) et qu'elle n'est pas entre guillemets , elle est candidate pour le "développement d' accolade ". Plus de contrôles sont effectués sur la structure interne plus tard.
Ainsi, ceci: est
{ls,-l}
qualifié d '"extension de support" pour devenirls -l
, en tant quefirst word
ouargument
(dans bash, zsh est différent).Mais ce ne sera pas:
{ls ,-l}
. Bash se divisera spaceet analysera la ligne en deux mots:{ls
et,-l}
qui déclenchera uncommand not found
(l'argument,-l}
est perdu):Votre ligne:
{ls;echo hi}
ne deviendra pas une "extension Brace" à cause des deux méta-caractères ;et space.Il sera divisé en ces trois parties:
{ls
nouvelle commande:echo
hi}
. Comprenez que cela ;déclenche le démarrage d'une nouvelle commande. La commande{ls
ne sera pas trouvée et la prochaine commande sera impriméehi}
:S'il est placé après une autre commande, il lancera quand même une nouvelle commande après le ;:
liste
L' une des « commandes composé » est une « liste Brace » (mes mots):
{ list; }
.Comme vous pouvez le constater, il est défini avec des espaces et une fermeture
;
.Les espaces et ;sont nécessaires parce que les deux
{
et}
sont « réservées mots ».Et par conséquent, pour être reconnu comme un mot, il doit être entouré de méta-caractères (presque toujours:) space.
Comme décrit au point 2 de la page liée
Votre exemple:
{ls;echo hi}
n'est pas une liste.Il faut une fermeture ;et un espace (au moins) après {. Le dernier }est défini par la fermeture ;.
Ceci est une liste
{ ls;echo hi; }
. Et ceci{ ls;echo hi;}
est également (moins couramment utilisé, mais valide) (Merci @choroba pour l'aide).Mais comme argument (le shell connaît la différence) à une commande, il déclenche une erreur:
Mais faites attention à ce que vous pensez que la coque analyse:
la source
;
et}
.{ ls;}
fonctionne comme le point-virgule est déjà un méta-caractère.Le bloc
{
est un mot-clé shell, il doit donc être séparé du mot suivant par un espace. En mode d'accolade, il ne doit pas y avoir d'espace (si vous devez accoler pour agrandir un espace, vous devez y échapper:)echo {\ ,a}{b,c}
.Vous pouvez utiliser le développement d'accolade au début d'une commande:
Cependant, vous ne pouvez pas l'utiliser pour développer un bloc, car l'analyse des commandes de regroupement a lieu avant les extensions:
la source
Il sait en vérifiant la syntaxe de la ligne de commande. De la même manière, il sait que dans l'expression
echo echo
, le premier écho doit être traité comme une commande et le deuxième comme un paramètre du premier écho.En bash c'est très simple, puisque
{ cmd; }
devrait avoir des espaces et des points-virgules. Cependant, par exemple en zsh, ils ne sont pas nécessaires, mais néanmoins, en analysant le contexte du{}
shell, on peut dire ce qu'il faut faire avec son contenu.Considérer ce qui suit:
Les deux renvoient la date actuelle, mais
retourne
1 2 3
parce que le shell connaît{}
un argument de commandeecho
, il devrait donc être développé.la source
{
suivi d'un espace non cité ne commence pas l'expansion de l'accolade dans bash.{
. L'espace non entre guillemets ne peut être n'importe où car le shell divise la ligne de commande entière en espacesTout d’abord, l’accolade composée doit être un mot et le premier mot de la ligne de commande:
Deuxièmement, les accolades individuelles ne sont pas spéciales (comme vous pouvez le voir ci-dessus). Les accolades vides ne sont pas spéciales:
Tout ce qui est sans virgule est aussi juste
Voici où l'action commence.
Donc, fondamentalement, pour que l’attelle se développe, nous avons besoin d’un seul mot (non séparé en champs sur des espaces), dans lequel se trouve au moins une instance
{...}
dans laquelle se trouve au moins une virgule.Cela peut être le premier mot de la ligne de commande, au fait:
la source