Shebang 以 `//` 开头?

Shebang 以 `//` 开头?

我对以下脚本感到困惑(hello.go)。

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

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

就可以执行了。 (在 MacOS X 10.9.5 上)

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

我还没听说过以 开头的 shebang //。当我在脚本顶部插入空行时它仍然有效。为什么这个脚本有效?

答案1

它不是一个 shebang,它只是一个由默认 shell 运行的脚本。 shell执行第一行

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

这会导致go使用该文件的名称进行调用,因此结果是该文件作为 go 脚本运行,然后 shell 退出而不查看文件的其余部分。

//但为什么要从 just/或适当的 shebang开始呢#!

这是因为该文件需要是有效的 go 脚本,否则 go 会抱怨。在 go 中,这些字符//表示注释,因此 go 将第一行视为注释,并且不会尝试解释它。然而,该字符#并不表示注释,因此当 go 解释文件时,普通的 shebang 会导致错误。

这种语法的原因只是为了构建一个既是 shell 脚本又是 go 脚本的文件,而不需要互相踩踏。

答案2

它运行是因为默认情况下可执行文件被假定为 /bin/sh 脚本。即,如果您没有指定任何特定的 shell - 它就是#!/bin/sh。

// 在路径中被忽略 - 您可以将其视为单个“/”。

所以你可以认为你有第一行的 shell 脚本:

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

这条线有什么作用?它使用参数“go run $0 $@”运行“env”。其中“go”是命令,“run $0 $@”是参数,然后退出脚本。 $0 是该脚本名称。 $@ 是原始脚本参数。所以这一行运行 go ,它用它的参数运行这个脚本

正如注释中指出的,有一些非常有趣的细节,两个斜杠是实现定义的,如果该脚本指定三个或更多斜杠,则该脚本将变得 POSIX 正确。参考http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html有关如何在路径中处理斜杠的详细信息。

另请注意,脚本 $@ 中还有另一个错误,使用“$@”是正确的,因为否则如果任何参数包含空格,它将被拆分为许多参数。例如,如果不使用“$@”,则无法传递带空格的文件名

这个特定的脚本显然依赖于“//”等于“/”的想法

答案3

这适用于 C++(如果 C 允许 // 注释,则适用于 C)

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

相关内容