Shebang以`//`开头?


60

我对以下脚本(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开头//。当我在脚本顶部插入空白行时,它仍然有效。为什么该脚本有效?


//&>/dev/null;x="${0%.*}";[ ! "$x" -ot "$0" ]||(rm -f "$x";cc -o "$x" "$0")&&exec "$x" "$@" ...
REINSTATE MONICA -Jeremy Banks 2014年

2
在下面的@ g-man和Jörg评论之后,并根据gilles的答案(unix.stackexchange.com/a/1919/27616),应该使用此技巧///....而不是//...使其最兼容!
奥利维尔·杜拉克

1
这将无法正确处理带有空格且没有更多引号的参数(或目录中的位置):go run "$0" "$@"
Charles Duffy 2014年

Answers:


71

这不是shebang,它只是由默认shell运行的脚本。外壳程序执行第一行

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

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

但是,为什么从一开始//而不是公正/或适当的射手开始#!呢?

这是因为文件需要是有效的go脚本,否则go会抱怨。在go中,字符//表示注释,因此go将第一行视为注释,并且不尝试对其进行解释。#但是,该字符不表示注释,因此正常的shebang在go解释文件时会导致错误。

语法的原因仅是建立一个既是shell脚本又是go脚本的文件,而又没有一个文件。


10
它是由内核而不是外壳处理的。请参阅Gilles 关于Linux如何处理多个路径分隔符的答案(/ home ///// username /// file)
G-Man

3
@HermanTorjussen功能-路径的语法定义得很好,允许使用许多有用的变体-并且随着功能的增加而变得复杂:/路径的后缀定义为/.; 如果a不是一个符号,a是相同的a/是一样的a/.尊者的情况下,一个路径可以得到额外的/与意义没有变化。推导规范路径时,存在一个标准化步骤,将连续的斜杠收缩为一个。当然,这并不是正式语法的一部分。
Volker Siegel 2014年

13
实际上,POSIX表示,多个斜线与单个斜线相同,除非在路径的开头恰好有两个斜线。就像这里的情况一样。在这种情况下,路径的解释取决于实现方式:“如果路径名以两个连续的<slash>字符开头,则后面的<slash>字符后的第一个组件可以以实现定义的方式进行解释,尽管两个前导<slash>字符应被视为单个<slash>字符。”
约尔格W¯¯米塔格

11
因此,要使其便于携带,应该改写///usr/bin/env go run $0 $@ ; exit...
Ruslan 2014年

1
@geek shell退出,但在启动go解释器之前没有退出。Go在打印你好世界,而不是外壳。
casey 2014年

8

它之所以运行,是因为默认情况下假定可执行文件为/ bin / sh脚本。即,如果您未指定任何特定的外壳,则为#!/ bin / sh。

//仅在路径中被忽略-您可以考虑将其视为单个'/'。

因此,您可以考虑使用第一行的shell脚本:

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

这条线是做什么的?它运行'env',参数设置为'go run $ 0 $ @'。那里的'go'是命令,'运行$ 0 $ @'是args,然后退出脚本。$ 0是此脚本名称。$ @是原始脚本参数。因此,此行运行go,并使用其参数运行此脚本

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

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

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


9
“ //在路径中只是被忽略” –不能保证:“如果路径名以两个连续的<slash>字符开头,则后面的<slash>字符后的第一个组件可以以实现定义的方式进行解释”(pubs .opengroup.org / onlinepubs / 9699919799 / basedefs /…–JörgW
Mittag

非常有趣,更新的答案。
gena2x 2014年

1
... // AFS的实现方式有所不同,//但是不再常见。
Charles Duffy 2014年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.