3

我最近才开始编程 scala,在“Scala 编程”(www.artima.com/pins1ed) 一书中,介绍了以下在 linux 中执行 scala 脚本的方法:

#!/bin/sh
exec scala "$0" "$@"
!#
// Say hello to the first argument
println("Hello, "+ args(0) +"!")

现在我已经使用 linux 很长时间了,但是 bash 脚本不是我的专长。现在我可以猜到这种类型的 scrpt 是如何工作的(而且效果很好),但我想知道 !# 和 $@ 到底是做什么的。

提前感谢所有帮助!

4

4 回答 4

4

!#与 Bash 没有任何关系。它是 Scala 语言的一部分。它在脚本模式下将非 Scala 标头与 Scala 代码分开。

于 2013-09-02T09:11:06.857 回答
4

确实很漂亮。$0"$@"是位置参数($0= 命令本身,就像argv[0]在 C 中和argv[1]+for一样"$@"),而#!*告诉 shell,有时是内核,如果它识别出要为文件执行哪个程序。

这里实际发生的事情是,shell 打开脚本以读取输入,但在 点exec,它将输入传输到 scala,但 scala 不必从头开始再次读取它,因为文件描述符仍然打开并且所以 scala 继续阅读下一行。

我很少看到脚本可以通过简单明了地展示其功能来做到这一点。

请注意,它exec替换了运行脚本的 shell 的进程,因此就像 shell 变成了 scala,但 scala 将具有相同的环境变量和打开的处理程序。

更新

看来我错了。Scala 本身会读取整个内容,但会跳过它可以看到的标题行。所以这是真正的目的!#

脚本文件可能有一个可选的标头,如果存在则被忽略。有两种方式来格式化标题:要么以#开头!并以 !# 结尾,或以 ::# 开头!并以 ::!# 结尾。

于 2013-09-02T09:07:12.920 回答
2

"$@"表示所有脚本参数。

于 2013-09-02T09:05:12.133 回答
2

您询问了 "$@" 究竟做了什么。它以非分词方式将参数传递给脚本。让我们看一些例子:

$ cat echowrap
#!/bin/sh
set -x
echo $*
echo $@
echo "$@"

$ ./echowrap oneword 'two words'
+ echo oneword two words
oneword two words
+ echo oneword two words
oneword two words
+ echo oneword 'two words'
oneword two words

在第一个示例中,$*已拆分输入参数,以便 echo 看到三个单词。第二个示例的$@行为相同。第三个示例"$@"没有进行分词,因此 echo 看到与最初传递的相同的 2 个 args。

考虑一个更有用的例子;如果您将脚本称为

$ ./scalascript 'Joe Bloggs'

然后尝试更改"$@"$@or $*,shell 会传递两个参数给 scala,scala 会看到 args(0) 和 args(1),测试程序的输出会有所不同。

于 2013-09-02T10:02:33.687 回答