エイリアス
%
になります。(以下ForEach-Objectはエイリアスの%
で表記します。)ファイル名の一覧を取得するサンプル
ls . | % { $_.Name }
ls(Get-ChildItem)でカレントディレクトリのファイルオブジェクトの一覧(配列など)をパイプラインで%(ForEach-Object)に渡します。{}内で各ファイルオブジェクトが一つずつ処理されます。(こちらの{}は-process {}の省略系になります)
$_はパイプラインで渡された配列などの一覧の要素になります。今回のサンプルではlsから出力されたファイルのファイルオブジェクトに当たります。ファイルオブジェクトのName
プロパティを取り出します。
{}内で変数や関数の戻り値を代入や引数などに用いない場合、コマンドレットの戻り値として扱われ、次のパイプラインがある場合コマンドレットに渡されます。
以下は一連のパイプラインの結果を$filesに代入するサンプルになります。
$files = ls . | % { $_.Name }
$filesには配列としてファイル名の一覧が代入されます。
結果をテキストファイルに出力する例
ls . | % { $_.Name } | Out-File output.txt
文字コードはPowerShellによって異なりますが、改行区切りのテキストファイルが出来上がります。
結果をクリップボードに出力する例
ls . | % { $_.Name } | Set-Clipboard
結果をメモ帳に貼り付けたり、Excelのセルに貼り付けたりすることが出来ます。
-begin,-process,-endオプションについて
以下のサンプルでは、0から4の値が表示されます。
@("1", "2", "3") | % -begin { "0" } -process { $_ } -end { "4" }
使い方として-begin{}には-process{}で実行する処理の前処理を-endは後始末を記述すると良いでしょう
-begin,-process,-endの実行される順番
@(1,2,3) | % -begin{"begin1"} { sleep 1; $_ } -end {"end1"} | % -begin{"begin2"} { Write-Host ("値:{0}" -f $_) } -end {"end2"}
結果
begin2
値:begin1
値:1
値:2
値:3
値:end1
end2
実行順番はbegin、process、endの順番で、初めの%(Foreach-Object)が完了後次の%(Foreach-Object)へ一括で渡されるのではなく、各要素ごと処理されていることが確認出来ます。一見するとbegin2とbegin1の出力順が逆の様に見えますが、実際の処理はbegin1→begin2の順番に処理されています。
単独オブジェクトを処理する
$txtbox1 = [System.Windows.Forms.TextBox]::new() % {
$_.Size = "100,100"
$_.Location = "10,10"
$_
}
繰り返す処理は1回なのでForEach-Objectを使う意味は無さそうですが、プロパティの初期化を{}にまとめることが出来ます。
要素の追加及び削除
@(1,2,3) | % { ($_ * 2 - 1); ($_ * 2) }
結果
1
2
3
4
5
6
同様に出力をコントロールすることで要素を削除することも出来ます。
@(1,2,3) | % { if ($_ -ne 2) { $_ } }
結果
1
3
要素の絞り込みであればForEach-ObjectよりもWhere-Objectを使う方法を検討した方が良いと思います。
複数のフィールドを持つデータを扱う
例
@("A","B","C") | % -begin{$i=0} { [PSCustomObject]@{"Index"=$i++; "Value"=$_} }
結果
Index Value
----- -----
0 A
1 B
2 C
PowerShellには汎用的に使えるPSCustomObjectがありますので、こちらオブジェクトを連想配列からキャストすることで生成します。
コメント