19

问题

我愿意将参数传递给 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")
4

4 回答 4

13

那么选项呢-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一流的

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

于 2017-10-15T15:40:41.760 回答
2

甲骨文真的搞砸了,没有好办法做到这一点。除了@mko 的回答,如果您使用 Linux(可能也可以在 Mac 上工作),您还可以使用process substitution

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

然后你可以使用arg例如myscript.jsh

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

您可以使用一些 bash 函数对其进行简化,并可能编写一个批处理文件,该文件将写入临时文件并在 Windows 上执行相同操作。

于 2017-10-15T21:15:22.500 回答
2

甲骨文怎么会忽略这一点,这完全超出了我的理解。8-() 但无论如何:如果您的系统使用 bash 作为 shell,您可以将这种替换 shebang 的方法与(ab-)使用系统属性将整个命令行传输到变量中的想法结合起来:

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

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

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

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

另一个变体是使用 bash 的进程替换动态生成脚本。thisscript.jsh arg1 arg2您也可以在具有 bash 的类 Unix 系统上简单地使用这样的脚本。

#!/usr/bin/env bash
jshell <(
cat <<EOF
System.out.println("$1");
System.out.println("$2");
/exit
EOF
)

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

#!/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"并附加 a",以将参数转换为有效的 Java 数组。

于 2019-01-17T21:24:15.707 回答
0

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

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

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

/exit

使用 Hans 的标题行,然后像 Oleg 演示的那样内联,它将 $@ args 构建到一个String[] argsvar 中。

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

]$ ./script.jsh foo bar
RESULT: [test, bar]
于 2021-11-27T03:02:38.803 回答