今までコマンドプロンプトばかり使っていた私が、PowerShellを使い始めて戸惑った点の備忘録です。
分かりやすくするためにJavaで下記のようなプログラムを書きました。
public class Main {
    public static void main(String[] args) {
        System.out.print("key1=");
        System.out.println(System.getProperty("key1"));
        System.out.print("key2=");
        System.out.println(System.getProperty("key2"));
    } 
}このプログラムに対して、java -Dkey1=abc -Dkey2=def Main.java とすると実行結果は以下になります。
E:\>java -Dkey1=abc -Dkey2=def Main.java
key1=abc
key2=def-Dkey1=abc -Dkey2=defという部分を環境変数に設定して実行することもできます。
E:\>set OPTIONS=-Dkey1=abc -Dkey2=def
E:\>java %OPTIONS% Main.java
key1=abc
key2=defさて、同じことをPowerShellで行ってみます。
PS E:\> java -Dkey1=abc -Dkey2=def Main.java
key1=abc
key2=def
ここまではコマンドプロンプトと同じです。引き継いだ環境変数をそのまま使って実行してみます。
PS E:\> $env:OPTIONS
-Dkey1=abc -Dkey2=def
PS E:\> java $env:OPTIONS Main.java
key1=abc -Dkey2=def
key2=nullなんとkey1に"abc -Dkey2=def"が設定されてしまいました。これは環境変数だけでなく、PowerShellの変数でも同じで、1変数が1引数として渡ってしまうようです。
PS E:\> $OPT="-Dkey1=ABC -Dkey2=DEF"
PS E:\> $OPT
-Dkey1=ABC -Dkey2=DEF
PS E:\> java $OPT Main.java
key1=ABC -Dkey2=DEF
key2=nullJavaを起動するバッチなどで実行時オプションをひとまとめにして 環境変数JAVA_OPTIONSに設定しておくことをよくやっていましたが、これができなさそうです。
結論としましては、splitメソッドを使って空白で分割することで問題を回避できるようです。バッチをシェルスクリプトへ移植する際は気を付けないといけませんね。
PS E:\> $OPTS = ($OPT.split(' '))
PS E:\> java $OPTS Main.java
key1=ABC
key2=DEF
PS E:\>ちなみに$OPTSは配列型になっているみたいです。
PS E:\> $OPTS.GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String[]                                 System.Array
PS E:\>
追記。久しぶりにコマンドラインからJavaのプログラムを実行してみたらコンパイルしないでも実行できるようになっててビックリ。
