What is the meaning of !# (bang-pound) in a sh / B

2019-03-11 03:53发布

I want to understand how this Scala script works:

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

On line 3, what is "!#" doing? Is the remainder of the file then fed to standard input of the Scala program? Also, is '!#' documented anywhere?

NB: The nearest thing I could find, although it is not directly relevant in any way is Stack Overflow question Why do you need to put #!/bin/bash at the beginning of a script file? (about the beginning of a Bash script).

3条回答
我欲成王,谁敢阻挡
2楼-- · 2019-03-11 03:58

When I removed !# in the sample program in BluesRockAddict's answer, I get the following error at the console:

error: script file does not close its header with !# or ::!# one error found

From the above error message, I understood the following things:

  1. !# is the close tag for the header exec scala "$0" "$@", which probably tells Scala that whatever comes after !# is the Scala code to be executed.
  2. !# can be replaced with ::!#.
查看更多
虎瘦雄心在
3楼-- · 2019-03-11 04:09

From the original documentation:

Script files may have an optional header that is ignored if present. There are two ways to format the header: either beginning with #! and ending with !#, or beginning with ::#! and ending with ::!#.

So the following code is just a header for a Scala script:

#!/usr/bin/env bash
exec scala "$0" "$@"
!#
查看更多
相关推荐>>
4楼-- · 2019-03-11 04:22

Based purely on experimentation (I assume this is described somewhere):

Beginning with Scala 2.10.0, the non-standard (from a POSIX scripting POV) pound-bang (!#) is no longer required in a POSIX shell environment. The following single line works (but must be the first line of the script, with no leading spaces):

#!/usr/bin/env scala

However, the only way to provide a shebang in a windows batch file is to trick it into calling Scala with itself as the first argument. Consequently, Scala needs to know where the last line of the batch file is, and therefore requires the closing ::!# line. Here's a working example:

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

Correction: I originally had #!/usr/bin/env scalav (notice the trailing v), which is my script to define property "scala.script", add some libraries to the classpath, before 'exec scala' itself. That way it's possible to determine the name of the script that is being executed, although scalav must then be in your PATH.

查看更多
登录 后发表回答