簡體   English   中英

PowerShell 刪除或跳過 CSV 中的列

[英]PowerShell Delete or Skip Columns in CSV

首先:我是 PowerShell 菜鳥。 我幾乎沒有使用 PowerShell 修改或更改 CSV 文件的經驗。

我們的系統給出了一種不常見的 CSV 格式,如下所示:

Example1;Example2;Name;Lastname;ContentOfExample1;ContentOfExample2;John;Doe

標題位於信息前面的每一行。 我想去掉一些列,比如 Example1 和 Example2。

作為第二步,我需要分配一個新標題

-Header Name,Lastname,Adress,Phone,..等。

我很感謝任何提示:-)

根據定義,此模式導致偶數個“;” 分隔元素。 您可以利用這一點,通過算術將屬性分配給對象,然后將它們重新發送到新的 CSV 文件。

可能看起來像:

Get-Content C:\Temp\InitialCSVFile.csv |
ForEach-Object{
    $TempArr  = $_.Split( ';' )
    $TempHash = [Ordered]@{}
    For($i = 0; $i -lt ($TempArr.Count / 2); ++$i)
    {
        $TempHash[ $TempArr[ $i ] ] = $TempArr[ $i+4 ]
    }
    [PSCustomObject]$TempHash
} |
Export-CSV -path C:\Temp\TestCSV.csv -NoTypeInformation -Append -Delimiter ';'

代碼將文件內容作為純字符串讀取,而不是像 CSV 這樣的半結構化格式。 當每一行都通過管道傳送到ForEach-Object.Split()字符串方法正在創建一個數組( $_ -split ';'也可以)。 我們實例化一個 Hash/Dictionary 對象來保存一些鍵值對。 完成后,將使用傳統的 For 循環來引用 kay 名稱和值。 名稱是元素 0,因此它的值應該是 0+4。 注意:循環被編碼為在數組的中間點停止。 這就是為什么我之前提到的偶數元素很重要!

哈希表完成后,代碼將其轉換為[PSCustomObject]並將其通過管道發送到Export-CSV ,這當然處理對象。 這應該會生成一個類似於以下內容的新 CSV 文件:

Example1          Example2          Name Lastname
--------          --------          ---- --------
ContentOfExample1 ContentOfExample2 John Doe
ContentOfExample1 ContentOfExample2 John Doe

注意:顯然數據是多余的,因為我只是在輸入文件中重復了您的示例。 這應該不是您的實時數據的問題。

注意:可能不需要重復重新創建$TempHash ,因為我們將在每個循環內部迭代中重新分配每個鍵的值。 現在我讓這個例子保持原樣。

更新:排除屬性:

$ExcludeProperties = @( 'Example1', 'Example2' )

Get-Content C:\Temp\InitialCSVFile.csv |
ForEach-Object{
    $TempArr  = $_.Split( ';' )
    $TempHash = [Ordered]@{}
    For($i = 0; $i -lt ($TempArr.Count / 2); ++$i)
    {
        $TempHash[ $TempArr[ $i ] ] = $TempArr[ $i+4 ]
    }
    [PSCustomObject]$TempHash
} |
Select-Object -Property * -ExcludeProperty $ExcludeProperties |
Export-CSV -path C:\Temp\TestCSV.csv -NoTypeInformation -Append -Delimiter ';'

確實是一種輸出 CSV 的奇怪方式..

你可以做的是用分隔符分割第一行; 為了獲得每列的標題。

一旦你有了它,剩下的就不應該太難了:

$csv = Get-Content -Path 'D:\Test\blah.csv' | Where-Object {$_ -match '\S'}

$parts = $csv[0] -split ';'
# calculate the number of parts that make up the headers
[int]$numberOfHeaders = $parts.Count / 2
# join the headers into a string
$header = $parts[0..($numberOfHeaders - 1)] -join ';'
# cut off the headers from every line
$rows = foreach ($line in $csv) { $line.Substring($header.Length + 1) }

# convert to an array of objects, skip the first two columns and export to a new file
$header, $rows | ConvertFrom-Csv -Delimiter ';' | 
    Select-Object * -ExcludeProperty $parts[0..1] | 
    Export-Csv -Path 'D:\Test\blah2.csv' -Delimiter ';' -NoTypeInformation

假設列數可能是隨機的並且要排除的屬性是已知的,您可以執行以下操作將您的數據解析為自定義對象:

Get-Content file.csv | Foreach-Object {
    $count = 0 # Tracks column counts to split the row evenly
    $cols = $_ -split ';'
    # $headers gets the first half of the columns. $data gets the remainder.
    $headers,$data = $cols.where({$count++ -lt $cols.count/2},'Split')
    # Uses calculated properties to add your new properties. You will need to fill in your own logic since you provided none here.
    ($headers -join ';'),($data -join ';') | ConvertFrom-Csv -Delimiter ';' |
        Select-Object *,@{n='Address';e={'Electric Avenue'}},@{n='Phone';e={'867-5309'}} -exclude example1,example2
}

如果 csv 文件中的所有數據都包含相同的標題,則可以使用Export-Csv從數據創建正確的 CSV:

Get-Content file.csv | Foreach-Object {
    $count = 0 # Tracks column counts to split the row evenly
    $cols = $_ -split ';'
    $headers,$data = $cols.where({$count++ -lt $cols.count/2},'Split')
    ($headers -join ';'),($data -join ';') | ConvertFrom-Csv -Delimiter ';' |
        Select-Object *,@{n='Address';e={'Electric Avenue'}},@{n='Phone';e={'867-5309'}} -exclude example1,example2
} | Export-Csv output.csv -NoType

如果每一行都可以有不同數量的列,那么您可能需要每行一個 CSV 文件,除非您解析所有數據並確定所有可能的列名。 如果您想保持與源格式相同的格式,但只想操作列和數據,您可以執行以下操作,這將適用於不同數量的列:

Get-Content file.csv | Foreach-Object {
    $count = 0 # Tracks column counts to split the row evenly
    $cols = $_ -split ';'
    $headers,$data = $cols.where({$count++ -lt $cols.count/2},'Split')
    $newObj = ($headers -join ';'),($data -join ';') | ConvertFrom-Csv -Delimiter ';' |
        Select-Object *,@{n='Address';e={'Electric Avenue'}},@{n='Phone';e={'867-5309'}} -exclude example1,example2
    "{0};{1}" -f ($newObj.psobject.properties.name -join ';'),($newObj.psobject.properties.value -join ';')
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM