PowerShellのパイプを更に利用/nl、wc -l自作

考えてみれば当たり前ですが、ちょっと感動したので記録。bash 等における $() に対応するものだと考えています。あと ForEach-Object ですが、「awkじゃん」ってなったのでそれも合わせて。

ForEach-Object で配列

次のコマンドを考えてみましょう。偶数を生成するものです。

PS > 1..5 | %{$_ * 2}
2
4
6
8
10

いまコンソールに出ているのはそれぞれの Int 型配列の要素たちです。これをひとまとめにすると Int 型の配列になります。実際画面になぜ数値が出るかというと、行き場を失ったデータが内部で Write-Host に解釈されて出ていくのでした。
とすると、その行き場を失ったデータをとどめてやれば配列を返したことになるのでは?ということです。やってみます。

PS > $arr = 1..5 | %{$_ * 2}
PS > $arr
2
4
6
8
10
PS > $arr[1]
4

おー!出ています。そしてどうやら =| よりも演算優先度が低いようですね。例えばこんなつなぎ方も良いわけですよね。

PS > $arr = 1..5
PS > $arr
1
2
3
4
5
PS > $arr = $arr | %{$_ * 2}
PS > $arr
2
4
6
8
10

この例では ForEach-Object の返り値に値を渡して、そのまま返り値を格納してしまっている例です。便利便利。

ForEach-Objectawk

見出しの通りです。awk には BEGIN ブロックと END ブロックがありますが、ForEach-Object にもありました!

PS > 1..10 | % -begin{write-host hey} {$_*2} -end {write-host ho!}   hey
2
4
6
8
10
12
14
16
18
20
ho!

こんな感じです。中間の部分は {} の前に -process を付けてもいいそう。そちらのほうが見やすいですね。

nl コマンドを作ってみた

欲しくなります。というわけでサクッと自作してみました。多分汎用性はないですので逐次状況に合わせて作っていきたいなぁと。

PS > ls -1 | % -begin {$a=0} {(++$a).tostring() + " " + $_.tostring()}
1 2N7002.log
2 2n7002.png
3 AWKTC
4 Adlm
5 Applications
6 Applications (Parallels)
7 BitBar
8 C-prototype.vim
9 CLionProjects
10 C_codegolf_memo.md
11 DAPLink
12 DCMouseCircuit
13 Desktop
...

ちなみに変数 $a はコマンド実行後にも生きていて、行数を確認できます。

PS > $a
182

私のホームディレクトリ…散らかりすぎ?

じゃあ Wc -l も簡単じゃん

と今思ったので作りますかね。

PS > ls -1 | % -begin {$a=0} {$a++} -end{$a}
182

と簡単にできました〜〜