如何将参数传递给 jshell 脚本?

How to pass arguments to a jshell script?

问题

我愿意将参数传递给 jshell 脚本。例如,我会喜欢这样的东西:

jshell myscript.jsh "some text"

然后让字符串 "some text" 在脚本中的某个变量中可用。

但是,jshell 只需要一个文件列表,因此答案是:

File 'some text' for 'jshell' is not found.

有什么方法可以正确地将参数传递给 jshell 脚本吗?

到目前为止的解决方法

到目前为止,我唯一的解决方案是在调用脚本时使用环境变量:

ARG="some test" jshell myscript.jsh

然后我可以在脚本中访问它:

System.getenv().get("ARG")

还有选项 -R

> jshell -v -R-Da=b ./file.jsh

脚本

{
  String value = System.getProperty("a");
  System.out.println("a="+value);
}
/exit

会给你

> jshell -v -R-Da=b ./file.jsh
a=b

另一种方式如下:

{
  class A {
    public void main(String args[])
    {
        for(String arg : args) {
          System.out.println(arg);
        }
    }
  }

  new A().main(System.getProperty("args").split(" "));
}

并执行

> jshell -R-Dargs="aaa bbb ccc" ./file_2.jsh

更新

先前的解决方案将因更复杂的参数而失败。例如。 'This is my arg'.

但我们可以从 ant 中获益,它是 CommandLine class

import org.apache.tools.ant.types.Commandline;
{
  class A {
    public void main(String args[])
    {
      for(String arg : args) {
        System.out.println(arg);
      }
    }
  }

  new A().main(Commandline.translateCommandline(System.getProperty("args")));
}

然后,我们可以这样称呼它:

jshell --class-path ./ant.jar -R-Dargs="aaa 'Some args with spaces' bbb ccc" ./file_2.jsh
aaa
Some args with spaces
bbb
ccc

当然,ant.jar必须在通过--class-path

传递的路径中

Oracle真的搞砸了,没有什么好办法。除了 and if you use Linux(probably will work on Mac too) you can use process substitution.

jshell <(echo 'String arg="some text"') myscript.jsh

然后您可以在 myscript.jsh 中使用 arg 例如:

System.out.println(arg) // will print "some text"

您可以使用一些 bash 函数来简化它,并且可能会编写一个批处理文件,该文件将写入临时文件并在 windows.

上执行相同的操作

我完全无法理解 Oracle 怎么会忽略这一点。 8-() 但无论如何:如果你的系统使用 bash 作为 shell,你可以组合 replacing the shebang with the idea to 将整个命令行传输到一个变量中:

//usr/bin/env jshell --execution local "-J-Da=$*" "[=10=]"; exit $?
String commandline = System.getProperty("a");
System.out.println(commandline);
/exit

这样,您可以在命令行上调用脚本,只需添加参数:thisscript.jsh arg1 arg2 将打印 arg1 arg2.

请注意,这会将所有参数连接成一个字符串,由一个 space 分隔。您可以使用 commandline.split("\s") 再次拆分它,但请注意这并不准确:两个参数 a b 和一个参数 "a b" 之间没有区别。

如果您有固定数量的参数,您也可以使用 "-J-Darg1=" "-J-Darg2=" "-J-Darg3=" 等将所有这些参数传递到单独的系统属性中。请注意,如果您不使用,则必须使用 -R-D...

另一种变体是使用 bash 的 动态生成脚本。在具有 bash.

的类 Unix 系统上,您也可以简单地使用这样的脚本 thisscript.jsh arg1 arg2
#!/usr/bin/env bash
jshell <(
cat <<EOF
System.out.println("");
System.out.println("");
/exit
EOF
)

这允许访问单个参数,但当参数中有双引号或其他特殊字符时它会中断。扩展这个想法:这是一种将所有参数放入 Java 字符串数组的方法,引用其中一些字符:

#!/usr/bin/env bash
set -- "${@//\/\\}"
set -- "${@//\"/\\"}"
set -- "${@/#/\"}"
set -- "${@/%/\",}"
jshell <(
cat <<EOF
String[] args = new String[]{$@};
System.out.println(Arrays.asList(args));
/exit
EOF
)

set -- 语句双反斜杠、引用双引号和前缀 a " 并附加 ", 以将参数转换为有效的 Java 数组。

最近,我受到 Oleg 和 Hans-Peter Störr 的回答的启发,足以尝试将它们结合起来,以便 a) 我可以使用正常的 shell 参数 b) 编写常规的 Java需要 String[] args 输入的代码:

//usr/bin/env jshell <(ARGS=; for var in "$@"; do ARGS+="\"$var\","; done; echo "String[] args = {$ARGS}") "[=10=]"; exit $?

System.out.println("RESULT: " + Arrays.asList(args));

/exit

使用 Hans 的 header 行,然后按照 Oleg 的演示进行内联,将 $@ args 构建到 String[] args var.

有了它,您可以 chmod +x 您的脚本并使用常规的旧参数执行它:

]$ ./script.jsh foo bar
RESULT: [test, bar]