2013/03/16

PowerShellのforループで2変数を初期化するにはどうすれば良いのかと、昨日とある方に質問されました。C#やJavaScriptなんかでは

for (int i = 0, j = 10; i < 10; i++, j--){}

のように初期化子を,で区切って複数指定できますが、PowerShellでは

for ($i = 0, $j = 10; $i -lt 10; $i++, $j--){}

という書き方ができません。初期化子部分には一つの変数しか書けないのです。

そこで考えたのが部分式を利用する方法です。部分式は一つの式に複数の文を埋め込むための書式で、

Write-Host "今日は $($d = Get-Date; $d.ToString("M/dd")) です。"

こんな感じで$()の中に複数の文を入れて変数のように実行結果の値を参照できます。なお、部分式の内部は、スクリプトブロックとは違い、外側と同じスコープとなります。

この部分式をforループの初期化子に利用してみます。

for ($($i = 0; $j = 3); $i -lt 3; $i++, $j--)
{
    "$i $j"
}

実行結果は

0 3
1 2
2 1

となりちゃんと動いてますね。

この書き方が果たして正式なものなのか、分かりませんが、forループで複数値の初期化をしたいときに使えるテクなんじゃないでしょうか。

ちなみにPowerShellのforループの初期化子宣言はループ内のスコープにおける変数とはならず、ループの外側でも参照や代入ができてしまいますので注意です。forループの中は別スコープとはならないのですね。それは部分式を使っても同じです。(それだったらforループの前で変数初期化しても同じことじゃん、となるかもしれませんが…)

また例をみていただければ分かりますが、反復式の部分は,で複数指定できるようです。ただしこの,はforステートメントの構文の一部ではなく、配列連結演算子の,だと思います。

追記。エントリ読み返して気づいたんですが、反復式を配列として記述できるのだから、初期化も配列でやっちゃえば良かったですね。このように。

for ($i, $j = 0, 3; $i -lt 3; $i++, $j--)
{
    "$i $j"
}

こっちのほうがいいですね。


Copyright © 2005-2016 Daisuke Mutaguchi All rights reserved

mailto: mutaguchi at roy.hi-ho.ne.jp

Awards

Books

Twitter