我有大型CSV文件(每个50-500 MB)。在这些命令上运行复杂的power shell命令需要永久和/或遇到内存问题。
处理数据需要按公共字段进行分组,例如在ColumnA中。因此,假设数据已经按该列排序,如果我随机分割这些文件(即每个x-000行),那么匹配的条目仍然可以在不同的部分结束。 A中有数千个不同的组,因此将每个组拆分为单个文件将创建许多文件。
如何将其拆分为10,000-ah线路文件而不丢失组?例如。第1-13行是A列中的A1,第14-17行是A2等,第9997-10012行是A784。在这种情况下,我希望第一个文件包含行1-10012,下一个文件包含行10013。
显然我想要保留整行(而不仅仅是A列),所以如果我将所有生成的文件粘贴在一起,这将与原始文件相同。
答案 0 :(得分:3)
未经测试。这假定ColumnA是第一列,它是常见的逗号分隔数据。您需要调整创建正则表达式的行以适合您的数据。
$count = 0
$header = get-content file.csv -TotalCount 1
get-content file.csv -ReadCount 1000 |
foreach {
#add tail entries from last batch to beginning of this batch
$newbatch = $tail + $_
#create regex to match last entry in this batch
$regex = '^' + [regex]::Escape(($newbatch[-1].split(',')[0]))
#Extract everything that doesn't match the last entry to new file
#Add header if this is not the first file
if ($count)
{
$header |
set-content "c:\somedir\filepart_$count"
}
$newbatch -notmatch $regex |
add-content "c:\somedir\filepart_$count"
#Extact tail entries to add to next batch
$tail = @($newbatch -match $regex)
#Increment file counter
$count++
}
答案 1 :(得分:2)
这是我的尝试,它变得凌乱:-P它会在分割时将整个文件加载到内存中,但这是纯文本。它应该比导入的对象花费更少的内存,但仍然与文件的大小有关。
$filepath = "C:\Users\graimer\Desktop\file.csv"
$file = Get-Item $filepath
$content = Get-Content $file
$csvheader = $content[0]
$lines = $content.Count
$minlines = 10000
$filepart = 1
$start = 1
while ($start -lt $lines - 1) {
#Set minimum $end value (last line)
if ($start + $minlines -le $lines - 1) { $end = $start + $minlines - 1 } else { $end = $lines - 1 }
#Value to compare. ColA is first column in my file = [0] . ColB is second column = [1]
$avalue = $content[$end].split(",")[0]
#If not last line in script
if ($end -ne $lines -1) {
#Increase $end by 1 while ColA is the same
while ($content[$end].split(",")[0] -eq $avalue) { $end++ }
#Return to last line with equal ColA value
$end--
}
#Create new csv-part
$filename = $file.FullName.Replace($file.BaseName, ($file.BaseName + ".part$filepart"))
@($csvheader, $content[$start..$end]) | Set-Content $filename
#Fix counters
$filepart++
$start = $end + 1
}
file.csv:
ColA,ColB,ColC
A1,1,10
A1,2,20
A1,3,30
A2,1,10
A2,2,20
A3,1,10
A4,1,10
A4,2,20
A4,3,30
A4,4,40
A4,5,50
A4,6,60
A5,1,10
A6,1,10
A7,1,10
结果(我使用$minlines = 5
):
file.part1.csv:
ColA,ColB,ColC
A1,1,10
A1,2,20
A1,3,30
A2,1,10
A2,2,20
file.part2.csv:
ColA,ColB,ColC
A3,1,10
A4,1,10
A4,2,20
A4,3,30
A4,4,40
A4,5,50
A4,6,60
file.part3.csv:
ColA,ColB,ColC
A5,1,10
A6,1,10
A7,1,10
答案 2 :(得分:0)
这需要PowerShell v3(由于-append
上的Export-CSV
)。
另外,我假设您有列标题,第一列名为col1
。根据需要进行调整。
import-csv MYFILE.csv|foreach-object{$_|export-csv -notypeinfo -noclobber -append ($_.col1 + ".csv")}
这将为第一列中的每个不同值创建一个文件,并将该值作为文件名。