web-dev-qa-db-ja.com

PowerShellでcsvファイルを読み取る、ヘッダー行に重複がある

スクリプトでcsvファイルを読み取って、データに列名を割り当てようとしています。ただし、ファイルには同じ名前の複数の列があり、以下のグレードQA/QCおよびシンボルを参照してください。

 ID,Date,Water Level / Niveau d'eau (m),Grade,Symbol / Symbole,QA/QC,Discharge / Débit (cms),Grade,Symbol / Symbole,QA/QC
07QC008,2018-12-28T00:00:00-06:00,6.536,,,1,0.052,,,1

ここに以下のコードがありますが、ヘッダー行を削除して自分の列名を代替するように変更するにはどうすればよいですか?

$stations = import-csv “C:\Users\robm\Downloads\stations\SK_hourly_hydrometric.csv”
#$stations | Get-Member


ForEach ($station in $stations){
$ID = $($station.ID)
$Date = $($station.Date)
$WaterLevel = $($station."Water Level / Niveau d'eau (m)")
$GradeWL = $($station.Grade1)
$SymbolWL=$($station."Symbol / Symbole1")
$QAWL=$($station."QA/QC1")
#$Discharge=$($station."Discharge / Débit (cms)")
$Discharge=$($station."Discharge")
$GradeD=$($station.Grade2)
$SymbolG=$($station."Symbol / Symbole2")
$QAD=$($station."QA/QC2")
Write-Host $ID "|" $Date "|" $WaterLevel "|" $GradeWL "|" $SymbolWL "|" $QAWL "|" $Discharge "|" $GradeD "|" $SymbolG "|" $QAD
#Write-Host $Discharge
}
2
R.Merritt

重複したヘッダーをインポートすることはできません。
それらを無視して、独自の新しいヘッダー名を指定してください。

  • Get-Contentの代わりにImport-Objectを使用してください
  • 最初の行をスキップ
  • ヘッダーでConvertFrom-Csvを使用する
  • 出力に含めたくない列を(非)選択します
  • -Delimiter '|'でexport-csvを使用して、新しい適切なcsvを作成します
    (すべてのヘッダー/列が二重引用符で囲まれています)

## Q:\Test\2018\12\31\sf_947091.ps1
$FileIn = 'C:\Users\robm\Downloads\stations\SK_hourly_hydrometric.csv'
$FileOut= 'C:\Users\robm\Downloads\stations\SK_hourly_hydrometric_new.csv'

$stations = Get-Content $FileIn | Select-Object -Skip 1 |
    ConvertFrom-Csv -Header ID,Date,WaterLevel,GradeWL,SymbolWL,QAWL,Discharge,GradeD,SymbolG,QAD 

$stations | Select-Object -Exclude Discharge 

$stations | Select-Object -Exclude Discharge | Export-Csv $FileOut  -NoTypeInformation

画面への出力例:

ID         : 07QC008
Date       : 2018-12-28T00:00:00-06:00
WaterLevel : 6.536
GradeWL    :
SymbolWL   :
QAWL       : 1
Discharge  : 0.052
GradeD     :
SymbolG    :
QAD        : 1

$ FileOutのサンプル

> Get-Content $FileOut
"ID"|"Date"|"WaterLevel"|"GradeWL"|"SymbolWL"|"QAWL"|"Discharge"|"GradeD"|"SymbolG"|"QAD"
"07QC008"|"2018-12-28T00:00:00-06:00"|"6.536"|""|""|"1"|"0.052"|""|""|"1"

まったく異なるアプローチは、古いヘッダーを自動的に読み取ることです。
ハッシュテーブルに保存し、
それによって重複をチェックし、増加する番号を追加します

## Q:\Test\2018\12\31\sf_947091_".ps1
$FileIn = 'C:\Users\robm\Downloads\stations\SK_hourly_hydrometric.csv'

(Get-Content $FileIn | Select-Object -First 1) -split ',' |
ForEach-Object {$Header = @{};$i=0}{
    $key = $_
    $j = 1
    while ($Header.Containskey($key)){
      $key = ("{0}{1}" -f $_,++$j)
    }
    $Header.Add($key,++$i)
}
$NewHeader = ($Header.GetEnumerator()|Sort-Object Value|
    ForEach-Object {'"'+$_.Name+'"'}) -Join ','

$NewHeader

"ID","Date","Water Level / Niveau d'eau (m)","Grade","Symbol / Symbole","QA/QC","Discharge / D‚bit (cms)","Grade2","Symbol / Symbole2","QA/QC2"
0
LotPings

"lotpings"コメントに基づいて、CSVにダブルがないかどうかを検証する関数を書きました。また、タイトルからの引用が確実に削除されるようにします。

使用:

csv_header_numbering_when_doublefound("dir/myfile.csv");

function csv_header_numbering_when_doublefound($fname)
{
$file=Get-Content "$fname"
($file | Select-Object -First 1) -split ',' |
ForEach-Object {$Header = @{};$i=0}{
    $key = $_ -replace '"',''
    $j = 1
    while ($Header.Containskey($key)){
      $key = ("{0}{1}" -f $_,++$j)
    }
    $Header.Add($key,++$i)
}
$NewHeader = ($Header.GetEnumerator()|Sort-Object Value|
    ForEach-Object {'"'+$_.Name+'"'}) -Join ','


$NewHeader > $fname;
$file | select-object -skip 1 >> $fname

}
1
sebke CCU

最も単純な解決策は列番号を使用することですが、ヘッダーを https://docs.Microsoft.com/en-us/powershell/module/Microsoft.powershell.utility/importに従って置き換えることもできます。 -csv?view = powershell-6 。最後の列は

$station[10]
0
Gerard H. Pille