Loading...
itpowersell

[PowerShell] csv 読み込み,行数で型が違った件

まず,はじめに動作環境は Windows Server2008 R2です.
$PSVersionTable は下記.

#Powershell 初心者です.自分備忘録なので,正しいとは限りません.そこのとこよろしくお願いいたします

Name                           Value                                              
----                           -----                                              
CLRVersion                     2.0.50727.5485                                     
BuildVersion                   6.1.7601.17514                                     
PSVersion                      2.0                                                
WSManStackVersion              2.0                                                
PSCompatibleVersions           {1.0, 2.0}                                         
SerializationVersion           1.1.0.1                                            
PSRemotingProtocolVersion      2.1                                                

タイトルどおりの件なのですが,自分が引っかかってなかなか気づかなかったので備忘録として.
結論からいうと,1行なのか,複数行かによって各要素へのアクセス方法が違った感じです.

やりたいこと
{,} 区切りの csv を読み込んで,一行ずつ処理をすること.
PSv3 なら,{Import-Csv} を使えば, encoding も一緒にかけて,幸せ.

Import-Csv -Encoding Default $listName

ただ,今回はPSv2での読み込みなので,Import-CSVはちょっと置いておきますね.
データは,こんな感じに用意します.

サンプルデータ:sample_3.csv

name,sex,age
emily,f,16
nancy,f,20
hamada,m,50

とりあえず,読み込み・

Get-Content $listName_3 | ConvertFrom-Csv

結果表示.

name                        sex                         age                       
----                        ---                         ---                       
emily                       f                           16                        
nancy                       f                           20                        
hamada                      m                           50

そうそう,ちゃんと読み取れてますね.

各要素にアクセスしたいときは,こんな感じ.

$line =  Get-Content $listName_3 | ConvertFrom-Csv 
for ( $i=0; $i -lt $line.Length ;$i++) {
    Write-Host  "name-> "$line[$i].name" sex-> "$line[$i].sex" age-> "$line[$i].age   
}

結果.

name->  emily  sex->  f  age->  16
name->  nancy  sex->  f  age->  20
name->  hamada  sex->  m  age->  50

と,ここまでは順調なんですね.

私がハマったのは,データが1行分しかないときです.

サンプルデータ:sample_1.csv

name,sex,age
emily,f,16

同様に,読み込みます.

Get-Content $listName_1 | ConvertFrom-Csv

もちろん,ちゃんと読み取れてます.私には,先ほどとかわりがわからない…

name                        sex                         age                       
----                        ---                         ---                       
emily                       f                           16  

私の中では,$line.length は 1 になり, $line[0].name のようにアクセスできるものだと思っていました.まぁ,やってみると,怒られます.

型 System.Management.Automation.PSObject のオブジェクトにインデックスを付けることはできません。

どういうことなの?と思って,型を調べてみると↓

$line = Get-Content $listName_1 | ConvertFrom-Csv 
$line.GetType()
IsPublic IsSerial Name                                     BaseType               
-------- -------- ----                                     --------               
True     False    PSCustomObject                           System.Object

PSCustomObject?たしかに,エラーメッセージにも書いてある….
え,じゃあ複数行の時は??

IsPublic IsSerial Name                                     BaseType            
-------- -------- ----                                     --------            
True     True     Object[]                                 System.Array        

Array とか書いてある,たしかに複数行っぽく認識してる….

ということで,1行のときは配列として認識しないようです.
アクセスするときは,

$line.name , $line.sex, $line.age

みたいにしてあげるべきみたいですね.
CSVを読み込んで,別のコマンドに渡す,というようなスクリプトを書いていたのでテストデータを1行にすると
ずっと処理が正しく進まないので,不思議に思ってたらこういうことでした.
Get-content で Convert するときは,1行か複数行かちゃんと判別しないとダメなのかな.
Import-Csv もそのうち,調べてみます.

コメントを残す

メールアドレスが公開されることはありません。

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