Shebang“#!”开始,“!#”结束?

时间:2015-10-29 19:17:54

标签: bash scala shell shebang

我一直在使用shebang #!一段时间,今天遇到了一个令我困惑的用例。

有几种方法可以运行scala脚本,例如

#!/usr/bin/env scala 
println("hello world")

然而,我遇到了这个版本的shebang

#!/bin/sh
exec scala "$0" "$@"
!#
println("hello world")

看起来这个解决方案基本上首先调用bash,运行exec scala "$0" "$@"其中$0表示当前文件名,$@是位置数组中的输入参数。

我的问题是否意味着#!!#之间的所有内容都可以在bash中执行,

#!/bin/sh
exec scala "$0" "$@"
echo "oh Yeah"
!#
println("hello world")

它没有错误但是在stdout中没有给我“哦是的”,有人能向我解释这里发生了什么吗?

更新:在认识到!#是scala之后,我下载了scala的源代码并意识到它只出现在Lex Spoon编写的ScriptRunner.scala部分的评论中。

1 个答案:

答案 0 :(得分:9)

!#行对shell 没有任何意义

#!/bin/sh行表示脚本由/bin/sh执行。 exec scala "$0" "$@"行调用scala,将脚本及其参数的名称传递给scala命令。由于exec未返回,因此shell不会看到脚本的其余部分。

我不知道Scala,但我的有根据的猜测是,Scala解释器本身将从#!行到!#行的所有内容视为注释。然后它开始使用Scala语句println("hello world")执行。

简而言之,!#是Scala语法,而不是shell语法(但Scala语法旨在让它在shell脚本中像这样使用)。

快速查看Scala Language Specification,我还没有找到如何定义。在this question中提到但未解释。正如chepner 3的评论所暗示的那样,它可能是Scala解释器中的一个黑客,而不是实际语言语法的一部分。

som-snytt在Scala解释器中找到了实现此here的代码:

object ScriptSourceFile {
  /** Length of the script header from the given content, if there is one.
   *  The header begins with "#!" or "::#!" and ends with a line starting
   *  with "!#" or "::!#".
   */
...

但我想知道它是否有记录。