Estoy confundido acerca de seguir script ( hello.go
).
//usr/bin/env go run $0 $@ ; exit
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
Se puede ejecutar (en MacOS X 10.9.5)
$ chmod +x hello.go
$ ./hello.go
hello, world
No he oído hablar de shebang desde el principio //
. Y todavía funciona cuando inserto una línea en blanco en la parte superior del script. ¿Por qué funciona este script?
//&>/dev/null;x="${0%.*}";[ ! "$x" -ot "$0" ]||(rm -f "$x";cc -o "$x" "$0")&&exec "$x" "$@"
...
///....
lugar de//...
ser el más compatible.go run "$0" "$@"
Respuestas:
No es un shebang, es solo un script que se ejecuta mediante el shell predeterminado. El shell ejecuta la primera línea.
lo que hace
go
que se invoque con el nombre de este archivo, por lo que el resultado es que este archivo se ejecuta como un script go y luego el shell sale sin mirar el resto del archivo.Pero, ¿por qué comenzar en
//
lugar de solo/
o un shebang adecuado#!
?Esto se debe a que el archivo debe ser un script go válido, o go se quejará. En ir, los caracteres
//
denotan un comentario, así que ve ve la primera línea como un comentario y no intenta interpretarlo. Sin#
embargo, el carácter no denota un comentario, por lo que un shebang normal provocaría un error cuando go interpreta el archivo.Esta razón para la sintaxis es solo para construir un archivo que sea a la vez un script de shell y un script go sin que uno pise el otro.
fuente
/
como sufijo de ruta se define como/.
; Cuandoa
no es un enlace simbólico,a
es lo mismoa/
quea/.
Thera, son casos en los que una ruta puede obtener un adicional/
sin ningún cambio en el significado. Cuando se deriva una ruta canónica, hay un paso de normalización que contrae barras diagonales consecutivas. Sin embargo, no es una parte limpia de la sintaxis formal.///usr/bin/env go run $0 $@ ; exit
...Se ejecuta porque, por defecto, se supone que el archivo ejecutable es / bin / sh script. Es decir, si no especificó ningún shell en particular, es #! / Bin / sh.
El // simplemente se ignora en las rutas; puede considerar que está en un solo '/'.
Entonces puede considerar que tiene un script de shell con la primera línea:
¿Qué hace esta línea? Se ejecuta 'env' con los parámetros 'go run $ 0 $ @'. allí 'go' es el comando y 'run $ 0 $ @' son argumentos y sale del script después. $ 0 es el nombre de este script. $ @ son argumentos de guiones originales. Entonces esta línea se ejecuta y ejecuta este script con sus argumentos
Hay detalles bastante interesantes, como se señala en los comentarios, que dos barras están definidas por la implementación, y esta secuencia de comandos se corregirá POSIX si especifica tres o más barras. Consulte http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html para obtener detalles sobre cómo se deben manejar las barras en las rutas.
Tenga en cuenta también que hay otro error en el script: $ @ es correcto usar "$ @" en su lugar, porque de lo contrario, si algún parámetro contiene espacios, se dividirá en muchos parámetros. Por ejemplo, no puede pasar el nombre del archivo con espacios si no está usando "$ @"
Este script en particular obviamente se basa en la idea de que '//' es igual a '/'
fuente
Esto funcionará para C ++ (y C si ese C permite // para comentarios)
//usr/bin/env sh -c 'p=$(expr '"_$0"' : "_\(.*\)\.[^.]*"); make $p > /dev/null && $p'; exit
fuente