¿Shebang comienza con `//`?

¿Shebang comienza con `//`?

Estoy confundido acerca de seguir el script ( hello.go).

//usr/bin/env go run $0 $@ ; exit

package main
import "fmt"
func main() {
    fmt.Printf("hello, world\n")
}

Puede ejecutarse. (en MacOS X 10.9.5)

$ chmod +x hello.go
$ ./hello.go
hello, world

No he oído hablar de shebang que comience con //. Y sigue funcionando cuando inserto una línea en blanco en la parte superior del script. ¿Por qué funciona este script?

Respuesta1

No es un tinglado, es solo un script que se ejecuta mediante el shell predeterminado. El shell ejecuta la primera línea.

//usr/bin/env go run $0 $@ ; exit 

lo que hace goque 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é empezar con algo //justo /o adecuado en lugar de hacerlo #!?

Esto se debe a que el archivo debe ser un script go válido o go se quejará. En go, los caracteres //denotan un comentario, por lo que ve la primera línea como un comentario y no intenta interpretarla. Sin embargo, el carácter #no denota un comentario, por lo que un tinglado normal resultaría en un error cuando go interpreta el archivo.

Esta razón para la sintaxis es simplemente crear un archivo que sea a la vez un script de shell y un script go sin que uno se interponga sobre el otro.

Respuesta2

Se ejecuta porque, de forma predeterminada, se supone que el archivo ejecutable es el script /bin/sh. Es decir, si no especificó ningún shell en particular, es #!/bin/sh.

// simplemente se ignora en las rutas; puede considerar que está en un solo '/'.

Entonces puedes considerar que tienes un script de shell con la primera línea:

/usr/bin/env go run $0 $@ ; exit

¿Qué hace esta línea? Ejecuta 'env' con los parámetros 'go run $0 $@'. allí 'ir' es el comando y 'ejecutar $0 $@' son argumentos y luego sale del script. $0 es el nombre de este script. $@ son argumentos del script original. Entonces esta línea se ejecuta go, que ejecuta este script con sus argumentos.

Hay detalles bastante interesantes, como se señala en los comentarios, de que dos barras diagonales están definidas por la implementación, y este script se volvería correcto en POSIX si especifica tres o más barras diagonales. Referirse ahttp://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.htmlpara obtener detalles sobre cómo se deben manejar las barras diagonales 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 utiliza "$@".

Este script en particular obviamente se basa en la idea de que '//' es igual a '/'

Respuesta3

Esto funcionará para C++ (y C si ese C permite // comentarios)

//usr/bin/env sh -c 'p=$(expr '"_$0"' : "_\(.*\)\.[^.]*"); make $p > /dev/null && $p'; exit

información relacionada