在 sh/Bash shell 脚本中,!#(bang-pound)的含义是什么?

17

我想了解这个Scala脚本是如何工作的:

#!/usr/bin/env bash
exec scala "$0" "$@"
!#
object HelloWorld {
    def main(args: Array[String]) {
        println("Hello, world! " + args.toList)
    }   
}
HelloWorld main args

第3行的"!#"是在做什么?文件的剩余部分是否会被馈送到Scala程序的standard input中?另外,'!#' 在任何地方都有记录吗?

NB:我找到了最接近的问题,虽然它与此并没有直接关系,那就是Stack Overflow问题为什么需要在脚本文件开头放置#!/bin/bash?(关于Bash脚本的开头)。


2
本问题的Windows版本:https://dev59.com/l1nUa4cB1Zd3GeqPYCw3 - Luigi Plinge
3个回答

20

来自原始文档:

脚本文件可以有可选的头部,如果存在则会被忽略。有两种格式化头部的方式: 以 #! 开始并以 !# 结束,或者以 ::#! 开始并以 ::!# 结束。

所以以下代码只是一个 Scala 脚本的头部:

#!/usr/bin/env bash
exec scala "$0" "$@"
!#

好的。那么在“!#”之后的脚本内容会发生什么? - Jay Taylor
5
Scala运行它。exec内置函数会导致scala解释器替换shell,因此bash不会看到!#行。而且scala将忽略#!!#之间的所有内容。 - cHao
我认为这可能是它的工作方式,但我无法在任何地方找到相关文档。谢谢! - Jay Taylor

2
BluesRockAddict's answer的示例程序中,当我移除!#时,在控制台上会得到以下错误:

错误:脚本文件没有用!#或::!#关闭其标题 发现一个错误

从上述错误消息中,我了解到以下几点:
  1. !#是头部exec scala "$0" "$@"的关闭标记,它可能告诉Scala,!#后面的任何内容都是要执行的Scala代码。
  2. !#可以被替换为::!#

2

仅凭实验结果(我认为这应该在某处有说明):

从Scala 2.10.0开始,在POSIX shell环境中不再需要非标准的(从POSIX脚本的角度来看)井号-叹号(!#)。以下单行代码可以工作(但必须是脚本的第一行,没有前导空格):

#!/usr/bin/env scala

然而,在Windows批处理文件中提供shebang的唯一方法是欺骗它,使其将Scala作为第一个参数调用自身。因此,Scala需要知道批处理文件的最后一行在哪里,因此需要关闭::!#行。这是一个有效的示例:

::#!
call scala %0 %*
goto :eof
::!#

更正:我最初使用了 #!/usr/bin/env scalav(注意末尾的v),这是我的脚本,用于定义属性“scala.script”,将一些库添加到类路径中,在执行 'exec scala' 之前。这样就可以确定正在执行的脚本名称,但是 scalav 必须在您的 PATH 中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接