19

我可以在 Haskell 中做这样的事情:

#!/usr/bin/runghc
main=putStrLn "Hello World"

然后我可以运行它./hello.hs

我的问题是,为什么第一行被忽略了?haskell 中的注释以开头,--但第一行似乎仍然被忽略。它甚至加载到 ghci 中。这个技巧也适用于 Python 和 Perl。

但是当我在 Java 中做类似的事情时:

#!/usr/local/jdk1.6.0_13/bin/javac
...

Javac 给了我一个编译器错误。

那么这是如何工作的,我如何让它与 Java 一起工作呢?

谢谢。

4

8 回答 8

20

#!被命名为“ shebang ”,是一种执行脚本的 Unix 方式。当您要求操作系统执行一个文件时,它会发现这不是一个普通的 .exe 文件,并且 #! 在开始时用作一个魔术标记,指示操作系统在 #! 之后执行命令!并连接该命令,使该文件成为该命令的参数

如果 myfile.py 包含

#!/usr/bin/python

执行该文件与运行没有太大区别

$ /usr/bin/python myfile.py

我的 Haskell 知识很差。但是对于您的特定情况,runghc 命令似乎只是读取第一行,解析在该 #! 上给出的任何参数!行,将文件的其余部分写入临时文件并在该临时文件上运行 ghc(这将删除第一个留置权 - 有关更多信息,请参见 ghc 源中的 runghc.hs。)

如果你想用 javac 做同样的事情,你可以使用与 runghc 相同的方法。编写一个包装器,它吃掉文件的第一行,将文件的其余部分写入临时文件并在该文件上运行 javac。

于 2009-07-14T00:16:05.413 回答
5

如果您的文件是 hello.hs,并且第一行是“#!/usr/bin/runghc”,那么 shell 将执行:

/usr/bin/runghc hello.hs

第一行基本上告诉 shell 用什么来运行脚本。

至于 java 示例,第一行应该是运行脚本的可执行文件,而不是编译脚本的可执行文件。

于 2009-07-14T00:08:28.930 回答
2

我的问题是,为什么第一行被忽略了?haskell 中的注释以 -- 开头,但第一行似乎仍然被忽略。它甚至加载到 ghci 中。这个技巧也适用于 Python 和 Perl。

“技巧”在 Python 和 Perl 中有效,因为#在这些语言中开始注释,因此解释器将该行视为注释并忽略它。所以对他们来说,这没什么特别的。

在 Haskell 中,#不会开始评论,所以它不会正常工作。但是,GHC(也许还有其他实现,如果有记忆的话,拥抱也是如此)对于 shebang 线有一个特殊情况。如果文件的第一行以 开头#!,则将其视为注释。这种与语言规范的偏差已被完全纳入以使

$ chmod +x hello.hs
$ ./hello.hs

工作。它不起作用,javac因为没有内置用于 shebang 线的特殊情况。

于 2012-01-19T06:09:08.463 回答
1

shebang 仅适用于解释语言....它通常对编译器没有任何意义,在大多数情况下会出错

于 2009-07-14T00:08:47.807 回答
0

之所以可行,是因为 Python、Perl 和 Haskell 显然都是解释型语言。这是指定将运行脚本的解释器的标准 Unix 方式。Java 是一种编译语言,不能使用解释器运行。

于 2009-07-14T00:09:57.913 回答
0

Javac 是编译器,而不是解释器。

它缺乏交互模式,我认为这是导致“魔法”的原因。同样不适用于 GCC,因为它缺少相同的功能。

例如,dmd(D 编译器)是一个支持 interpertation 的编译器示例,具有这种交互式编辑(#!/usr/bin/dmd -run)。

于 2009-07-14T00:11:49.313 回答
0

它是计算机上用于解释脚本的可执行文件的位置。Java 是一种编译语言,因此不需要这样的声明。

此外,关键是它是一个特殊的注释,Java 中的构造以这种方式是不合法的,因为 # 不是合法的注释标记。如果这样的结构有意义......它没有......它看起来像:

//!/usr/local/jdk1.6.0_13/bin/javac

于 2009-07-14T00:14:40.483 回答
0

通过Wikipedia找到了对 shebang 行的引用,但这似乎是更好的文章。另见“#!” 关于各种 Unix 风格的 shebang 机制的魔法细节

于 2009-07-14T00:25:08.707 回答