LoginSignup
4
6

More than 3 years have passed since last update.

PowerShellの闇 - 配列の戻り値編

Last updated at Posted at 2019-09-19

突然ですがクイズです

csvのデータ件数を数えるPowerShellコマンドを実行します。
2行のcsvファイルに対して実行したところ、2が結果として表示されました。(先頭のAAA,BBBはcsvヘッダです)

test.csv
AAA,BBB
1,2
3,4
PowerShellコマンド
PS C:\Users\hoge> (import-csv test.csv).count
2

  
では、同じPowerShellコマンドを次のようなデータ1件のcsvファイルに実行したらどうなるでしょうか

test.csv
AAA,BBB
1,2

答え

何も表示されません

PS C:\Users\hoge> (import-csv test.csv).count
PS C:\Users\hoge>

いいたいこと

原因の解説

PowerShellのコマンドは結果の個数によって型が変わるものがあります。たとえば次のようになることがあります

結果の個数
2個以上 配列 @(1,2,3)
1個 要素単体 1
0個 $null $null

2個以上の時は配列なので.countで個数が取得できますが、1個の時は配列ではなく要素単体です。

1個の時は要素のcountプロパティへアクセスし、countプロパティがないと結果が$nullとなってしまいます。

データ1件のtest.csvでは(import-csv test.csv).count$nullになってしまうのが、
何も表示されなかった理由です。

なお、この挙動になるかどうかはコマンド次第です。import-csvget-aduserなんかでは起きます。
lsは要素がcountプロパティを持っていてかつ1を返すので、
結果が1個でも.count1を返してくれます

ちなみに$null.countはエラーではなく0になります。なので結果が0個なら.count0が表示されます

回避策

世間の記事では@()で包んで配列にするのが多いようです

@(import-csv test.csv).count

これだと確かに結果が1個の時は配列にできますが、
結果が2個以上の時は「配列の配列」になってしまい.count1を返すと思うかもしれません。

しかし、PowerShellは「配列の配列」は配列に変換するので、問題ありません。(むしろそのPowerShellの仕様が問題な気も
@(@(1,2,3)) => @(1,2,3)

別の方法として個数を数えるmeasureを使うこともできます。
配列だろうとオブジェクトだろうと$nullだろうとうまく数えてくれます

(import-csv test.csv | measure).count

| measureは配列の個数が多いと重くなるそうですが、そんなに多くない時は問題ありません。

さらなる闇

test.csvの中身をヘッダのみのデータ0件にしてみます

test.csv
AAA,BBB

データ0件のcsvでは確かに読み込み結果は$nullのようです...

PS C:\Users\hoge> (import-csv test.csv) -eq $null
True
PS C:\Users\hoge> $csv = (import-csv test.csv)
PS C:\Users\hoge> $csv -eq $null
True
PS C:\Users\hoge> $csv.gettype()
null 値の式ではメソッドを呼び出せません。
発生場所 :1 文字:1
+ $csv.gettype()
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) []RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

しかし@()で包むと挙動が$nullと違います。
$nullのようで$nullでは無い何かのようです・・・

PS C:\Users\hoge> @($csv).count
0
PS C:\Users\hoge> @($null).count
1
PS C:\Users\hoge> $a = $null
PS C:\Users\hoge> @($a).count
1

気が向けば次回でこのあたりの記事も書きます

参考

PowerShellのCountプロパティについてあれやこれや
そろそろ PowerShell の一次配列の罠と回避について一言いっておくか

補足

以上は PowerShell 5.1.18362.145 で動かしています。バージョンによって挙動が変わる部分もあるようなのでご注意ください

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6