【问题标题】:In Powershell Import a CSV , split into multiple files every 10 lines在 Powershell 中导入 CSV ,每 10 行拆分为多个文件
【发布时间】:2019-10-12 04:58:33
【问题描述】:

我是 powershell 编码的新手,我想做的是导入行数未知的 CSV 文件,然后每 10 行将其拆分为一个新的 CSV 文件。

例如,如果我输入一个 97 行的 CSV 文件,我期望 9 个 10 行的文件和 1 个 7 行的文件。

我尝试了以下方法,Hostlist.csv 包含 35 个主机名,我得到 3 个文件,第一个文件缺少列表中的第一个主机,并且没有剩余主机的第 4 个文件。

$Hostlist = Get-Content '.\Hostlist.csv'
$BatchID = Get-Random
New-Item -ItemType Directory -Force -Path .\$BatchID
$MaxBatch = 10
$line = 0
$i = 0
$File = 0

While ($line -lt $Hostlist.Length) {

    if ($i -gt $MaxBatch) {
        $Start = $line - $MaxBatch
        $File++
        $Hostlist[$Start..($line-1)] | Out-File ".\$BatchID\Batch$File.csv" -Append -force
        $i = 0
    }
    $i++;
    $line++
}

【问题讨论】:

    标签: powershell csv while-loop split chunks


    【解决方案1】:

    顺便说一句:

    • 如果您的输入文件是 CSV 文件,并且您希望输出文件也是 CSV 文件,则必须为每个文件写一个标题行。

    • 您的代码没有尝试这样做,所以我假设您只是在处理面向行的纯文本文件,尽管有 .csv 文件扩展名。

    第一个文件缺少第一个主机

    由于您处理批次的条件是$i -gt $MaxBatch,所以当您首先进入if 块时,$i$line 都是11,因此$Start = $line - $MaxBatch1,即second 行,假设 $Start 用作基于 0 的数组索引。

    没有剩余主机的第 4 个文件。

    由于您只处理$i -gt $MaxBatch 的批处理,因此其行数不能被$MaxBatch 整除的输入文件将始终丢失其最后一批,因为最后一个不完整的批处理永远不会满足if 条件。


    我建议通过计算批次数量并逐批次循环来简化您的代码,如下面的简化示例所示,它将 10 行输入分成 3 个批次:

    # Simulate the list of hosts
    $HostList = 1..10 -replace '^', 'host$&' # 'host1', 'host2', ...
    
    # Batch size
    $MaxBatch = 3
    
    foreach ($batch in 1..[math]::Ceiling($Hostlist.Count / $MaxBatch)) {
      write-verbose -Verbose "File index (batch number): $batch"
      $startNdx = ($batch-1) * $MaxBatch
      $Hostlist[$startNdx..($startNdx + $MaxBatch - 1)]
    }
    

    注意[math]::Ceiling() 在批次计数计算中的使用$Hostlist.Count / $MaxBatch 如何确保最后不完整的批次也被处理。

    除非您有Set-StrictMode -Version 3 或更高版本,否则可以超出.. 范围表达式中用于在最终的不完整批处理中对数组进行切片的数组上限 - PowerShell 将简单地忽略超出上限的索引绑定。

    以上产出:

    VERBOSE: File index (batch number): 1
    host1
    host2
    host3
    VERBOSE: File index (batch number): 2
    host4
    host5
    host6
    VERBOSE: File index (batch number): 3
    host7
    host8
    host9
    VERBOSE: File index (batch number): 4
    host10
    

    【讨论】:

    • 很高兴听到它有帮助,@Outableh;我的荣幸。
    【解决方案2】:

    您的代码不会生成正确的 CSV 文件,因为您没有处理标题信息,也没有使用 Import-CSV 让您处理自然导出为 CSV 的对象。所以我去了一些为另一个人编写的代码。

    $SourceDir = $env:TEMP
    $SourceFile = 'Source.csv'
    $FullSourceFile = Join-Path -Path $SourceDir -ChildPath $SourceFile
    
    $BatchSize = 4
    
    $OutputDir = $env:TEMP
    $OutputFile = 'Output.csv'
    $FullOutputFile = Join-Path -Path $OutputDir -ChildPath $OutputFile
    
    #$InCSV = Import-Csv -Path $FullSourceFile
    
    #region - fake reading in CSV
    # fake reading in a CSV file
    #    in real life, use Import-CSV above
    $InCSV = @'
    Col_1,Col_2,Col_3,Col_4
    row-1-1, row-1-2, row-1-3, row-1-4
    row-2-1, row-2-2, row-2-3, row-2-4
    row-3-1, row-3-2, row-3-3, row-3-4
    row-4-1, row-4-2, row-4-3, row-4-4
    row-5-1, row-5-2, row-5-3, row-5-4
    row-6-1, row-6-2, row-6-3, row-6-4
    row-7-1, row-7-2, row-7-3, row-7-4
    row-8-1, row-8-2, row-8-3, row-8-4
    row-9-1, row-9-2, row-9-3, row-9-4
    row-10-1, row-10-2, row-10-3, row-10-4
    '@ | ConvertFrom-Csv
    #endregion - fake reading in CSV
    
    $Count = 0
    $Remaining = $InCSV.Count
    $Batch = [System.Collections.Generic.List[PSObject]]::new()
    foreach ($IC_Item in $InCSV)
        {
        $Count ++
        $Ready = $False
    
        $Batch.Add($IC_Item)
    
        if ($Count -eq $BatchSize)
            {
            $Ready = $True
            $Count = 0
            }
    
        $Remaining --
        if ($Remaining -eq 0)
            {
            $Ready = $True
            }
    
        if ($Ready)
            {
            $TimeStamp = Get-Date -Format 'yyyy-MM-dd__HH-mm-ss__fff'
            $NewFullOutputFile = $FullOutputFile.Replace('.csv', "$TimeStamp.csv")
    
            $Batch | 
                Export-Csv -LiteralPath $NewFullOutputFile -NoTypeInformation
    
            $Batch.Clear()
            }
        }
    

    没有屏幕输出。这是第一个 CSV 的内容...

    "Col_1","Col_2","Col_3","Col_4"
    "row-1-1","row-1-2","row-1-3","row-1-4"
    "row-2-1","row-2-2","row-2-3","row-2-4"
    "row-3-1","row-3-2","row-3-3","row-3-4"
    "row-4-1","row-4-2","row-4-3","row-4-4"
    

    最后一个 CSV 的内容...

    "Col_1","Col_2","Col_3","Col_4"
    "row-9-1","row-9-2","row-9-3","row-9-4"
    "row-10-1","row-10-2","row-10-3","row-10-4"
    

    【讨论】:

    • @Outableh - 不客气!很高兴能帮上一点忙……mklement0 的答案确实是更好的答案。 [咧嘴]
    猜你喜欢
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多