Je suis confus de suivre script ( hello.go
).
//usr/bin/env go run $0 $@ ; exit
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
Il peut exécuter. (sur MacOS X 10.9.5)
$ chmod +x hello.go
$ ./hello.go
hello, world
Je n'ai pas entendu parler de shebang à partir de //
. Et cela fonctionne toujours lorsque j'insère une ligne vierge en haut du script. Pourquoi ce script fonctionne-t-il?
//&>/dev/null;x="${0%.*}";[ ! "$x" -ot "$0" ]||(rm -f "$x";cc -o "$x" "$0")&&exec "$x" "$@"
...
///....
au lieu d'//...
être la plus compatible!go run "$0" "$@"
Réponses:
Ce n'est pas un shebang, c'est juste un script qui est exécuté par le shell par défaut. Le shell exécute la première ligne
ce qui a
go
pour effet d'appeler le nom de ce fichier. Il en résulte que ce fichier est exécuté en tant que script go puis que le shell se ferme sans regarder le reste du fichier.Mais pourquoi commencer par
//
au lieu de juste/
ou d'un shebang approprié#!
?Cela est dû au fait que le fichier doit être un script valide, sinon Go se plaindra. Dans go, les caractères
//
désignent un commentaire, alors go voit la première ligne comme un commentaire et ne tente pas de l'interpréter. Le caractère#
cependant, ne représente pas un commentaire, donc une tralala normale entraînerait une erreur lors de passer interprète le fichier.Cette raison de la syntaxe est simplement de construire un fichier qui est à la fois un script shell et un script aller sans que l'un ne se place sur l'autre.
la source
/
comme suffixe de chemin est défini comme/.
; Quanda
n'est pas un lien symbolique,a
est identique àa/
ce qui est identique àa/.
Thera sont des cas où un chemin peut en obtenir un supplémentaire/
sans changement de sens. Lorsque vous dérivez un chemin canonique, il existe une étape de normalisation qui réduit les barres obliques consécutives à une barre oblique. Certes, cela ne fait cependant pas partie de la syntaxe formelle.///usr/bin/env go run $0 $@ ; exit
...Il s'exécute car, par défaut, le fichier exécutable est supposé être le script / bin / sh. C'est-à-dire si vous n'avez pas spécifié de shell particulier - c'est #! / Bin / sh.
Le // est simplement ignoré dans les chemins - vous pouvez le considérer comme un simple '/'.
Vous pouvez donc considérer que vous avez un script shell avec la première ligne:
Que fait cette ligne? Il fonctionne 'env' avec les paramenters 'go run $ 0 $ @'. il y a 'go' est command et 'run $ 0 $ @' sont des arguments et des scripts de sortie par la suite. $ 0 est ce nom de script. $ @ sont des arguments de script originaux. Donc, cette ligne lance go qui exécute ce script avec ses arguments
Comme indiqué dans les commentaires, il existe des détails assez intéressants selon lesquels deux barres obliques sont définies par l'implémentation, et ce script deviendrait POSIX-correct s'il spécifiait trois barres obliques ou plus. Reportez-vous à http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html pour plus de détails sur la manière dont les barres obliques doivent être traitées dans les chemins.
Notez également qu'il y a une autre erreur dans le script $ @ il est correct d'utiliser "$ @" à la place, car sinon, si un paramètre contient des espaces, il sera divisé en plusieurs paramètres. Par exemple, vous ne pouvez pas transmettre le nom de fichier avec des espaces si vous n'utilisez pas le "$ @"
Ce script particulier repose évidemment sur l'idée que '//' est égal à '/'
la source
Cela fonctionnera pour C ++ (et C si ce C autorise // pour les commentaires)
//usr/bin/env sh -c 'p=$(expr '"_$0"' : "_\(.*\)\.[^.]*"); make $p > /dev/null && $p'; exit
la source