Как выполнить сценарий Java с JShell?
Учитывая, что Java 9 на нас, и мы можем наконец получить Java REPL с jshell
Я надеялся, что есть способ добавить Шебанг в сценарий и иметь 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.
Есть ли другой способ сделать это?
3 ответа
Использование
//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
не является обязательным, конечно, но дает немедленную обратную связь, что инструмент работает
Дополнительная опция командной строки --execution local
предотвращает jshell
породить другую ВМ. Это ускоряет время запуска, и если код вашего сценария создает исключение, локальная виртуальная машина завершает работу.
Обратитесь к выводу jshell --help
а также jshell --help-extra
для большего количества вариантов.
Оказывается, что с небольшой хитростью есть способ, хотя мне не удалось полностью подавить интерпретированные команды, но довольно близко к тому, что я хочу.
+ Изменить 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
Ниже также работает; положить это в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/.
Вдохновленный steiny ответом, я придумал более общее решение
https://gist.github.com/ffissore/012d7e32a096fde5266f49038c93dcaf
По сути: jshell-wrapper
удалит первую строку сценария (которая должна быть Шебанг) и добавит /exit
в конце сценария