Il y a quelques mois, j'ai tatoué une bombe fourchue sur mon bras et j'ai sauté les espaces blancs, car je pense que c'est plus joli sans eux. Mais à mon grand désarroi, parfois (pas toujours) quand je le lance dans un shell, cela ne déclenche pas un fork bombe, mais cela donne simplement une syntaxe Erreur.
bash: syntax error near unexpected token `{:'
Hier, c’est arrivé quand j’ai essayé de le lancer dans un shell Bash d’un ami, puis j’ai ajouté le blanc et cela a fonctionné, :(){ :|:& };:
au lieu de :(){:|:&};:
Les espaces blancs sont-ils importants? ai-je tatoué une erreur de syntaxe sur mon bras?!
Il semble que cela fonctionne toujours dans zsh , mais pas dans Bash.
ne question connexe n'explique rien sur les espaces, ce qui est vraiment ma question; Pourquoi Bash doit-il disposer de l'espace nécessaire pour pouvoir l'analyser correctement?
Il existe une liste de caractères qui séparent les jetons dans BASH. Ces caractères sont appelés métacaractères et sont |
, &
, ;
, (
, )
, <
, >
, espace et tab. Par contre, les accolades ({
et }
) ne sont que des caractères ordinaires qui composent les mots.
L'omission du deuxième espace avant }
suffira, car &
est un métacaractère. Par conséquent, votre tatouage doit avoir au moins un caractère d'espace.
:(){ :|:&};:
Juste un tatouage
#!/bin/zsh
Shebang dessus et tout ira bien.
Les accolades ressemblent davantage à des mots-clés impairs qu'à des symboles spéciaux et nécessitent des espaces. Ceci est différent des parenthèses, par exemple. Comparer:
(ls)
qui fonctionne, et:
{ls}
qui recherche une commande nommée {ls}
. Pour travailler, il faut que:
{ ls; }
Le point-virgule empêche que l'accolade de fermeture soit prise en tant que paramètre pour ls
.
Tout ce que vous avez à faire est de dire aux gens que vous utilisez une police proportionnelle avec un caractère espace plutôt étroit.
Bien que cela ne soit pas facilement visible dans la police tatoo, il existe en fait une marque Byte-Order (BOM) entre le corset et le côlon (vous avez peut-être été suffisamment intoxiqué lorsque vous avez obtenu le tatouage pour ne pas l'avoir remarqué, mais c'est vraiment là) . Cela laisse trois possibilités évidentes:
et puis j'ai ajouté les espaces et ça a soudainement fonctionné ...
C'est à cause de la façon dont Shell analyse. Vous avez besoin d’un espace après le début de la définition de la fonction, c’est-à-dire après le {
.
foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}
sont valides. D'autre part,
foo() {echo hey&}
n'est pas.
Vous avez réellement besoin d'un tatouage comme celui-ci:
De la source :
/* We ignore an open brace surrounded by whitespace, and also
an open brace followed immediately by a close brace preceded
by whitespace. */
Si vous omettez un espace après le {
, le {echo
sera interprété comme un simple jeton.
Une forme équivalente de
:(){ :|:& };:
serait
:(){
:|:& };:
Notez qu'il n'y a pas d'espace après {
dans la version alternative, mais une coupure de ligne oblige le shell à reconnaître {
comme un jeton.