[PS1] Powershell の基本 (3:パイプライン処理)

2014年10月16日
  1. パイプラインの基本
    • パイプライン変数

       $_ が要素一つ一つ。

      PS> @(1,2,3) | % { $_; } 
      1
      2
      3
      

    • 列挙

       % {} で表現。{} 内に列挙時の処理を書く。
       % は ForEach-Object の Alias。Foreach とも書ける。

      PS > @(1..5) | % { $_ * 100; }
      100
      200
      300
      400
      500
      

    • 列挙 その2

       パイプラインの始端,または終端で、初期処理,あるいは終了処理がしたい場合は、% (ForEach) ではなく & (スクリプトブロックの実行)を用いる。
       begin {} の中に、初期処理を、
       process {} の中に、ForEach などで書いていた、パイプラインのコレクションごとの処理を、
       end {} の中に、終了処理を書く。

      PS > @(1..3) | &{
      >>  begin   { "初期処理"; }
      >>  process { $_ * 200; }
      >>  end     { "終了処理"; }
      >> }
      初期処理
      200
      400
      600
      終了処理
      

    • フィルタリング

       ? {} で表現。{} 内にフィルター条件の処理を書く。
       ? は Where-Object の Alias。Where とも書ける。
       処理の結果、0 (= $False),$null,結果がない、などの場合は、入力されたオブジェクトは次のパイプラインに渡さない。

      PS > @(1..5) | ? { $_ % 2; }
      1
      3
      5
      
  2. パイプラインへの出力

     パイプラインへ出力は、直接その値を記述することで行う。

    1. リテラルをパイプラインに出力
      PS> "AAA" | % { $_; } 
      AAA
      
    2. 出力先の指定がない場合の出力先

       最終出力先(変数代入やファイルへの出力)の指定が場合、パイプライン出力はコンソールに渡される。

      PS> @(1,2,3) | % { $_; }  # この文の実行でデータが表示される
      1
      2
      3
      
    3. 出力先を変数にした場合

       変数への代入するとコンソールに出力されずに、その内容が変数に格納される。

      PS> $a = @(1,2,3) | % { $_; } # この文の実行ではデータは表示されない
      PS> $a.Count #件数
      3
      PS> $a #内容
      1
      2
      3
      
    4. 複数の値を出力した場合

       それぞれがパイプラインへ出力される。

      PS> $a = @(1,2,3) | % { "****"; $_; $_; } 
      PS> $a.Count
      9
      PS> $a
      ****
      1
      1
      ****
      2
      2
      ****
      3
      3
      
    5. 次のパイプラインに出力を渡さない

       パイプラインへは出力されない場合。

      PS> $a = @(1,2,3) | % { } 
      PS> $a.Count
      0
      

       Write-Host の出力は パイプラインに出力されない。

      PS> $a = @(1,2,3) | % { Write-Host $_; }
      1
      2
      3
      PS> $a.Count
      0
      
  3. パイプラインを経由した処理の実行順

     パイプラインでつないだ場合、処理の実行順が一般的な言語とは異なる点に注意。
     パイプラインに出力するたびに、パイプラインの先の処理に制御が移る。
     パイプラインに渡す前までの処理をすべてやりきって、その結果をまとめて次のパイプラインに渡すわけではない。
     一般的の言語の場合だと、コルーチン(yeild) を使った動きに似ている。(*1)

    PS > @("A","B","C") |
    >> % { Write-Host "1st :$_";  $_ + "*"; } |
    >> % { Write-Host "2nd :$_";  $_ + "#"; } |
    >> % { Write-Host "3rd :$_"; }
    >>
    1st :A
    2nd :A*
    3rd :A*#
    1st :B
    2nd :B*
    3rd :B*#
    1st :C
    2nd :C*
    3rd :C*#
    

     括弧で囲むと、そこまでの処理が確定される。

    PS > (
    >>   @("A","B","C") |
    >>   % { Write-Host "1st :$_";  $_ + "*"; } |
    >>   % { Write-Host "2nd :$_";  $_ + "#"; }
    >> ) |
    >> % { Write-Host "3rd :$_"; }
    >>
    1st :A
    2nd :A*
    1st :B
    2nd :B*
    1st :C
    2nd :C*
    3rd :A*#
    3rd :B*#
    3rd :C*#
    


(*1) VB で同様の動きをさせようとすると、以下のようなコードで実現できる。

Module Module1
    Sub Main()
        Third(
            Second(
                First(
                    {"A", "B", "C"}
                    )
                )
            ).
        ToArray()
    End Sub

    Iterator Function First(input As IEnumerable(Of String)) As IEnumerable(Of String)
        For Each s In input
            Console.WriteLine("1st :" & s)
            Yield s & "*"
        Next
    End Function

    Iterator Function Second(input As IEnumerable(Of String)) As IEnumerable(Of String)
        For Each s In input
            Console.WriteLine("2nd :" & s)
            Yield s & "#"
        Next
    End Function

    Iterator Function Third(input As IEnumerable(Of String)) As IEnumerable(Of String)
        For Each s In input
            Console.WriteLine("3rd :" & s)
            Yield s
        Next
    End Function
End Module

 結果

1st :A
2nd :A*
3rd :A*#
1st :B
2nd :B*
3rd :B*#
1st :C
2nd :C*
3rd :C*#






タグ:
カテゴリー: PowerShell, Windows

Follow comments via the RSS Feed | Leave a comment | Trackback URL

コメントを投稿する

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


«   »
 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org