Как передать аргументы в jshell script?

Вопрос

Я готов передать аргументы в jshell script. Например, мне понравилось бы что-то вроде этого:

jshell myscript.jsh "some text"

а затем, чтобы строка "некоторый текст" была доступна в некоторой переменной внутри script.

Однако jshell ожидает только список файлов, поэтому ответ:

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

Есть ли способ правильно передать аргументы в jshell script?

Обходной путь

Моим единственным решением до сих пор является использование переменной среды при вызове script:

ARG="some test" jshell myscript.jsh

И затем я могу получить доступ к нему в script с помощью:

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

Ответ 1

А как насчет опции -R

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

для script

{
  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

Ответ 2

Oracle действительно испортил это, нет хорошего способа сделать это. В дополнение к @mko answer, и если вы используете Linux (вероятно, будете работать и на Mac), вы можете использовать замену процесса.

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

И тогда вы можете просто использовать arg в myscript.jsh, например:

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

Вы можете упростить его с помощью некоторой функции bash и, возможно, написать командный файл, который будет записывать в файл temp и делать то же самое в окнах.

Ответ 3

Это полностью вне меня, как Oracle мог игнорировать это. 8-() Но в любом случае: если ваша система использует bash в качестве оболочки, вы можете объединить этот подход, заменив 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 выведет arg1 arg2.

Обратите внимание, что это объединяет все параметры в одну строку, разделенные одним пробелом. Вы можете снова разделить его с помощью commandline.split("\s"), но имейте в виду, что это не точно: нет разницы между двумя параметрами ab и одним параметром "ab".

Если у вас есть фиксированное количество аргументов, вы также можете передать все их в отдельные системные свойства с помощью "-J-Darg1=$1" "-J-Darg2=$1" "-J-Darg3=$1" и т.д. Обратите внимание, что вы должны использовать -RD... если вы не используете --execution local

Другой вариант - создание сценария на лету с заменой процесса bash. Вы можете использовать такой скрипт также просто, как thisscript.jsh arg1 arg2 также в Unix-подобных системах, имеющих bash.

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

Это позволяет получить доступ к отдельным параметрам, но будет прерываться, если в параметре есть двойные кавычки или другие специальные символы. В продолжение этой идеи: вот способ поместить все параметры в массив строк Java, заключив в кавычки некоторые из этих символов:

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

Операторы set -- выполняют двойную обратную косую черту, заключают в кавычки двойные кавычки и set -- префикс " и добавить а ", чтобы преобразовать аргументы в допустимый массив Java.