4 Nashornとシェル・スクリプト
注意:
Nashornエンジン、jjs
ツール、およびjdk.scripting.nashornとjdk.scripting.nashorn.shellの各モジュールは、将来のリリースでの削除に備えてJDK 11では非推奨です。
Nashornのシェル・スクリプト拡張機能を有効にするには、-scripting
オプションを指定したjjs
コマンドを使用します。たとえば、次のコマンドは対話型モードでシェル・スクリプト拡張機能を有効にした状態でNashornを呼び出します。
jjs -scripting
標準のJavaScriptコメント(//
および/*
*/
)に加えて、Nashornは番号記号(#
)を使用するシェル形式のコメントもサポートします。スクリプトの最初の文字が番号記号である場合は、-scripting
オプションを指定せずにjjs
ツールを使用しても、スクリプトを解釈するときにNashornのシェル・スクリプト拡張機能が自動的に有効になります。これは、スクリプトの先頭にshebang (#!
)を指定して、スクリプトをシェル実行可能ファイルとして実行する場合に便利です。「Shebang」を参照してください。
Shebang
スクリプト・ファイルの先頭にshebang (#!
)を指定すると、そのスクリプト・ファイルをシェル実行可能ファイルとして実行できます。shebangにjjs
ツールのパスを指定すると、スクリプトを実行したときに、シェルがスクリプトではなくjjs
ツールを実行し、ツールにスクリプト・ファイルを渡します。
jjs
ツールは、JAVA_HOME/bin
ディレクトリ(JAVA_HOME
はJDKのインストール・ディレクトリ)にあります。JDKをインストールすると、通常はJAVA_HOME
環境変数が自動的に設定されます。自動的に設定されなかった場合や、複数のバージョンのJDKがインストールされている場合は、手動でJAVA_HOME
環境変数をJDKインストール・ディレクトリの正しいパスに設定します。
shebangにjjs
ツールの直接パスを指定できますが、次のように/usr/bin
ディレクトリにシンボリック・リンクを作成することをお薦めします。
>> cd /usr/bin
>> ln -s $JAVA_HOME/bin/jjs jjs
>>
注意:
場合によっては、sudo
を使用してルート特権でln
コマンドを実行する必要があります。
シンボリック・リンクを設定したら、実行可能ファイルとして実行できるNashornスクリプトを作成できます。また、shebang文にコマンド行オプションを直接追加することもできます。次の例のscriptArgs.js
は、Nashornエンジンのバージョンとスクリプトに渡された引数を出力する実行可能スクリプトを示しています。
#!/usr/bin/jjs -fv
print("Arguments: " + arguments);
scriptArgs.js
ファイルをシェル実行可能ファイルとして実行すると、このファイルはNashornによって次のように解釈されます。
>> ./scriptArgs.js -- arg1 arg2 arg3
nashorn full version 1.8.0
Arguments: arg1,arg2,arg3
>>
または、jjs
ツールのパスがPATH
環境変数に含まれている場合は、次のようにしてshebangにjjs
を指定できます。
#!/usr/bin/env jjs
文字列補間
文字列補間は、UNIXシェルで変数または式の値を含む文字列を作成するために使用されます。Nashornでシェル・スクリプト機能を有効にすると、同じようにして変数や式を文字列リテラルに埋め込むことができます。
たとえば、次のようにDate()
コンストラクタの結果をdate
変数に割り当て、ドル記号($
)と中カッコ({}
)を使ってこの変数を文字列に渡すことができます。
jjs> var date = Date()
jjs> "Date and time: ${date}"
Date and time: Mon Aug 19 2013 19:43:08 GMT+0400 (MSK)
前の例は、Date()
コンストラクタから返された値がdate
変数に割り当てられたときに、日付と時間を表示します。式が評価された時点の日付と時間を表示する場合は、次のようにDate()
コンストラクタを直接渡すことができます。
jjs> "Current date and time: ${Date()}"
Current date and time: Mon Aug 19 2013 19:49:53 GMT+0400 (MSK)
文字列補間は、二重引用符で囲まれた文字列でのみ機能します。一重引用符に囲まれた文字列は補間されません。
jjs> 'The variable is ${date}'
The variable is ${date}
ヒア・ドキュメント
ヒア・ドキュメント(heredoc)は、改行とインデントを保持した文字列をUNIXシェルに指定します。Nashornでシェル・スクリプト機能を有効にすると、heredocを含むスクリプトを評価できます。
次の例のscriptHereArgs.js
は、最初に渡された引数を1行目に出力し、2番目の引数をインデントして2行目に出力し、3番目の引数を(空白行の後で)4行目に出力する実行可能スクリプトを示しています。
#!/usr/bin/jjs
print(<<EOD);
${arguments[0]} is normal
${arguments[1]} is indented
${arguments[2]} is separated by a blank line
EOD
scriptHereArgs.js
ファイルをシェル実行可能ファイルとして実行すると、Nashornエンジンによって次のように解釈されます。
>> ./scriptHereArgs.js -- Line1 Line2 Line3
Line1 is normal
Line2 is indented
Line3 is separated by a blank line
グローバル・オブジェクト
Nashornでシェル・スクリプト機能を有効にすると、いくつかのグローバル・オブジェクトが定義されます。
-
$ARG
-
このグローバル・オブジェクトを使用すると、
arguments
オブジェクトを使用する場合と同じようにして、スクリプトに渡された引数にアクセスできます。例:>> jjs -scripting -- arg1 arg2 arg3 jjs> $ARG arg1,arg2,arg3 jjs> $ARG[1] arg2
-
$ENV
-
このグローバル・オブジェクトは、現在のすべての環境変数をマップします。例:
jjs> $ENV.USER johndoe jjs> $ENV.PWD /foo/bar
-
$EXEC()
-
このグローバル・オブジェクトは、コマンドを実行するためのプロセスを起動します。例:
jjs> $EXEC("ls -l") total 0 drwxr-xr-x+ 1 johndoe staff 4096 Aug 18 11:03 dir -rwxrw-r-- 1 johndoe staff 168 Aug 19 17:44 file.txt jjs>
$EXEC()
関数は、2つ目の引数を取ることもできます。この引数は、プロセスの標準入力(stdin
)として使用される文字列です。jjs> $EXEC("cat", "Send this to stdout") Send this to stdout jjs>
注意:
コマンドに入力が不要な場合は、バッククォートによる文字列表記を使ってプロセスを起動できます。たとえば、
$EXEC("ls -l")
のかわりに`ls -l`
を使用できます。 -
$OPTIONS
-
このオブジェクトは、nashornの「コマンド・ライン」に渡されるコマンド行オプションを公開します。次に例を示します。
jjs> print("-scripting=" + $OPTIONS_scripting); jjs> print("--compile-only=" + $OPTIONS_compile_only); jjs> print("-timezone="+ $OPTIONS_timezone.ID);
-
$OUT
-
このグローバル・オブジェクトは、プロセスの最新の標準出力(
stdout
)を格納するために使用されます。たとえば、$EXEC()
の結果は$OUT
に保存されます。 -
$ERR
-
このグローバル・オブジェクトは、プロセスの最新の標準エラー(
stderr
)を格納するために使用されます。 -
$EXIT
-
このグローバル・オブジェクトは、プロセスの終了コードを格納するために使用されます。終了コードがゼロでない場合、そのプロセスは失敗しています。
その他のNashorn組込み関数
Nashornは、いくつかの組込み関数を定義しています。echo
、readLine
およびreadFully
関数は、-scripting
モードにのみ定義されます。quit
、exit
、load
、loadWithNewGlobal
、Object.bindProperties
などの他の拡張機能は、常に利用できます。
- quit()
- exit()
-
これらの関数は同義であり、現在のスクリプト・プロセスを終了してシステムに戻ります。システムに返す終了コードを表す整数値を引数として渡すことができます。デフォルトでは、引数を指定しなかった場合の終了コードは、プロセスが正常に終了したことを意味する0に設定されます。
- print()
- echo()
-
これらの関数は同義であり、引数として渡された値を文字列に変換し、空白で区切って
stdout
に出力し、続いて改行を出力します。この実装は、java.lang.System.out.print(string)
を呼び出した後でjava.lang.System.out.println()
を呼び出します。>> jjs -scripting -- arg1 jjs> var a = "Hello" jjs> print(123, $ARG[0], a, "World") 123 arg1 Hello World jjs>
- readLine()
-
この関数は、
stdin
の入力を1行だけ読み取り、それをstdout
に送ります。または、結果を変数に割り当てることができます。次の例のように、文字列をreadLine()
関数に渡してプロンプト行を作成することもできます。jjs> var name = readLine("What is your name? ") What is your name? Bob jjs> print("Hello, ${name}!") Hello, Bob! jjs>
- readFully()
-
この関数は、文字列引数として渡されたファイルの内容全体を読み取り、それを
stdout
に送ります。または、結果を変数に割り当てることができます。jjs> readFully("text.txt") This is the contents of the text.txt file located in the current working directory. jjs>
readFully()関数は、メソッドbyte[] Files.readAllBytes(Path)を使用してデータを読み取り、返されたバイト配列でバイト・オーダー・マーク(BOM)検出を実行して、読み取ったデータがUnicodeでエンコードされているかどうかを判定します。
- load()
-
この関数は、パス、URLまたはスクリプト・オブジェクトからスクリプトをロードして評価します。
jjs> load("/foo/bar/script.js") jjs> load("http://example.com/script.js") jjs> load({name:"script.js", script:"var x = 1 + 1; x;"})
- loadWithNewGlobal()
-
この関数は
load()
関数とほぼ同じですが、新しいグローバル・オブジェクトを使用してスクリプトが評価されます。これは、スクリプト評価用の新しいコンテキストを作成するための主な手段です。loadWithNewGlobal()
に(スクリプトの後で)渡された追加の引数は、新しいコンテキストのarguments
グローバル変数に格納されます。 -
Object.bindProperties(target, source)
-
この関数を使用して、
source
オブジェクトのプロパティをオブジェクトtarget
にバインドします。この関数を使用することで、グローバル・プロパティの共有が可能になります。たとえば、Document Object Model (DOM)のシミュレーションでは、グローバル・オブジェクトとドキュメントの間でプロパティを共有できます。マルチスレッド・アプリケーションでは、スレッドのグローバル・オブジェクト間で関数を共有できます。次の例は、
obj
オブジェクトのプロパティをグローバル・オブジェクトにバインドする方法を示しています。jjs> var obj = {x:34,y:100} jjs> obj.x 34 jjs> obj.y 100 jjs> x <shell>:1 ReferenceError: "x" is not defined jjs> Object.bindProperties(this,obj) [object global] jjs> x 34 jjs> y = Math.PI 3.141592653589793 jjs> obj.y 3.141592653589793 jjs>
関数Object.bindProperties(target, source)は、targetに存在しないsourceのプロパティのみをバインドすることに注意してください。次の例に、関数bindPropertiesは
obj
オブジェクトのプロパティをグローバル・オブジェクトにバインドしようとしています。ただし、x
プロパティはすでにグローバル・オブジェクトに存在しています。したがって、関数bindPropertiesは、obj.x
をグローバルのx
にバインドしません。そのため、obj.x
の値を変更しても、グローバルのx
の値は変更されませんjjs> x = 2 2 jjs> var obj = {x:3} jjs> Object.bindProperties(this,obj) [object global] jjs> x 2 jjs> x = 4 4 jjs> obj.x 3 jjs> x 4