【问题标题】:How to execute a java script with jshell?如何使用 jshell 执行 java 脚本?
【发布时间】:2017-07-05 03:36:25
【问题描述】:

鉴于 Java 9 即将到来,我们终于可以使用 jshell 获得 Java REPL,我希望有一种方法可以将 shebang 添加到脚本并让 jshell 解释它。

我尝试创建test.jsh

#!/usr/bin/env jshell -s
System.out.println("Hello World")
/exit

但是这给出了:

⚡ ./test.jsh
|  Error:
|  illegal character: '#'
|  #!/usr/bin/env jshell -s
|  ^
|  Error:
|  illegal start of expression
|  #!/usr/bin/env jshell -s
|    ^
Hello World

原来在 OpenJDK https://bugs.openjdk.java.net/browse/JDK-8167440 中有一个增强请求。

还有其他方法吗?

【问题讨论】:

    标签: java shebang java-9 jshell


    【解决方案1】:

    使用

    //usr/bin/env jshell --show-version --execution local "$0" "$@"; exit $?

    作为test.jsh 的第一行。 test.jsh 脚​​本可能如下所示:

    //usr/bin/env jshell --show-version "$0" "$@"; exit $?
    System.out.println("Hello World")
    /exit
    

    当然,命令行选项--show-version 是可选的,但会立即提供工具正在运行的反馈。

    extra 命令行选项--execution local 可防止jshell 生成另一个VM。这加快了启动时间,如果您的脚本代码引发异常,本地 VM 将退出。

    更多选项请查阅jshell --helpjshell --help-extra 的输出。

    更新

    还可以查看https://github.com/jbangdev/jbang 玩转 Java 脚本,它提供了从命令行运行 .java 文件的简洁包装。

    【讨论】:

    【解决方案2】:

    事实证明,虽然我还没有完全设法抑制解释命令,但有点诡计有一种方法,但非常接近我想要的。

    test.jsh 更改为:

    #!/usr/bin/env sh
    tail -n +4 "$0" | jshell -s "$@"
    exit $?
    System.out.println("Hello World")
    /exit
    

    这给了我们:

    ⚡ ./test.jsh
    -> System.out.println("Hello World")
    Hello World
    -> /exit
    

    【讨论】:

      【解决方案3】:

      受 steiny answer 的启发,我想出了一个更通用的解决方案

      https://gist.github.com/ffissore/012d7e32a096fde5266f49038c93dcaf

      本质上:jshell-wrapper 将删除脚本的第一行(应该是 shebang)并在脚本末尾添加一个/exit

      【讨论】:

      • 不错的脚本,但其中 2 个可以并行启动吗?
      • 它们将是 2 个不同的进程,所以为什么不呢
      • 我正在考虑TMP='mktemp' 的用法,这似乎是一个文件,最终被许多线程使用,每个线程都可能使用不同的 jsh 文件。
      • mktemp 每次调用都会创建一个新文件
      • 你是对的;现在我注意到这不是一个名字,而是 mktemp 的执行
      【解决方案4】:

      以下也适用;将其放入someScript.jsh 文件并使用./someScript.jsh 运行它。 someScript.jsh 收到的所有参数都将转到 String[] args

      #!/home/gigi/.sdkman/candidates/java/current/bin/java --source 11
      
      import java.util.Arrays;
      import ro.go.adrhc.*; // example of using your classes, e.g. App below
      
      public class X {
          public static void main(String[] args) {
              // do whatever you want here, e.g.:
              // System.out.println("Hello World");
              // or
              // use a class:
              // App.main(args);
              // e.g. from ro.go.adrhc package, by running:
              // CLASSPATH="/path-to-ro.go.adrhc-classes" ./someScript.jsh 
          }
      }
      

      包装类的使用,这里是X,是这个工作的必要技巧。
      灵感来自https://blog.codefx.org/java/scripting-java-shebang/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多