How to pass arguments to a jshell script?

2019-03-18 03:44发布

问题:

Question

I am willing to pass arguments to a jshell script. For instance, I would have liked something like this:

jshell myscript.jsh "some text"

and then to have the string "some text" available in some variable inside the script.

However, jshell only expects a list of files, therefore the answer is:

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

Is there any way to properly pass arguments to a jshell script?

Workaround so far

My only solution so far is to use an environment variable when calling the script:

ARG="some test" jshell myscript.jsh

And then I can access it in the script with:

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

回答1:

And what about option -R

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

for script

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

will give you

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

Another way, would be following:

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

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

and execution

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

Update

Previous solution will fail with more complex args. E.g. 'This is my arg'.

But we can benefit from ant and it's 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")));
}

and then, we can call it like this:

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

Of course, ant.jar must be in the path that is passed via --class-path



回答2:

Oracle really screwed this up, there is no good way to do this. In addition to @mko's answer and if you use Linux(probably will work on Mac too) you can use process substitution.

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

And then you can just use arg in myscript.jsh for example:

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

You can simplify it with some bash function and probably write a batch file that will write to a temp file and do the same on windows.



回答3:

It's completely beyond me how Oracle could ignore this. 8-() But anyway: if your system uses bash as shell, you can combine this approach replacing the shebang with the idea to (ab-)use system properties to transport the whole command line into a variable:

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

This way, you can call the script on the commandline simply adding the arguments: thisscript.jsh arg1 arg2 would print arg1 arg2.

Please note that this joins all parameters into one String, separated by one space. You can split it again with commandline.split("\s"), but please be aware that this isn't exact: there is no difference between two parameters a b and one parameter "a b".

If you have a fixed number of arguments, you can also pass all of these into separate system properties with "-J-Darg1=$1" "-J-Darg2=$1" "-J-Darg3=$1" etc. Please observe that you have to use -R-D... if you are not using --execution local

Another variant is generating the script on the fly with bash's process substitution. You can use such a script also simply as thisscript.jsh arg1 arg2 also on Unix-like systems having a bash.

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

This allows to access individual parameters, though it will break when there are double quotes or other special characters in a parameter. Expanding on that idea: here's a way to put all parameters into an Java String array, quoting some of those characters:

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

The set -- statements double backslashes, quote double quotes and prefix a " and append a ", to transform the arguments into a valid Java array.



标签: java-9 jshell