如何用Windows批处理脚本仅合并多个CSV中的唯一记录?
嘿,针对你这个超大规模CSV合并去重的问题,我刚好有几个实用的方案,毕竟处理1000万条记录可不能瞎折腾,得兼顾速度和准确性~
方案一:纯Windows批处理(利用原生sort命令)
如果你的CSV是整行重复,而且每个记录都是标准的单行格式(没有带引号的换行字段),用Windows自带的sort命令是最高效的选择——它支持大文件处理,而且/unique参数能直接去除重复行。
修改后的脚本如下,我会逐段解释:
@echo off setlocal enabledelayedexpansion :: 定义最终输出的去重后文件名 set "output_file=unique_combined.csv" :: 临时文件,用来存所有跳过表头的内容 set "temp_all=temp_all_records.csv" :: 临时文件,用来存排序去重后的内容 set "temp_unique=temp_unique_records.csv" :: 第一步:提取第一个CSV的表头,避免后续去重把表头干掉 for %%f in (*.csv) do ( set "first_csv=%%f" goto get_header ) :get_header if defined first_csv ( :: 提取第一行作为表头写入输出文件 for /f "delims=" %%a in ('type "!first_csv!"') do ( echo %%a > "%output_file%" goto header_extracted ) ) :header_extracted :: 第二步:合并所有CSV的内容,跳过每个文件的表头 echo 正在合并所有记录... del /q "%temp_all%" 2>nul for %%f in (*.csv) do ( :: 用more +1跳过当前文件的第一行(表头),追加到临时文件 more +1 "%%f" >> "%temp_all%" ) :: 第三步:排序并去重,/unique参数会自动保留唯一行 echo 正在排序去重... sort /unique "%temp_all%" > "%temp_unique%" :: 第四步:把去重后的内容追加到带表头的输出文件 type "%temp_unique%" >> "%output_file%" :: 清理临时文件 del /q "%temp_all%" "%temp_unique%" echo 处理完成!去重后的文件:%output_file% endlocal
关键说明:
sort /unique是核心:它会先对所有行排序,然后自动剔除重复的连续行,效率远高于逐行判断,非常适合1000万级别的数据。- 单独提取表头:避免多个CSV的表头被重复合并或误去重。
- 临时文件拆分:避免单步操作内存溢出,毕竟大文件直接处理容易出问题。
方案二:结合PowerShell(更灵活,支持按字段去重)
如果你的“重复记录”是指特定字段重复(比如某列ID重复,而非整行完全一致),纯批处理就很难实现了,这时候用PowerShell会更灵活——它能轻松指定按哪个字段去重,还能保留首次出现的记录。
下面是批处理调用PowerShell的脚本,同样兼顾大文件效率:
@echo off set "output_file=unique_combined.csv" :: 第一步:提取第一个CSV的表头 for /f "delims=" %%a in ('type "*.csv" ^| findstr /n "^" ^| findstr "^1:" ^| set /p "=" ^| findstr /v "^1:"') do ( echo %%a > "%output_file%" ) :: 第二步:用PowerShell合并、去重(这里按第一列字段去重,可自行修改) echo 正在处理去重... powershell -Command "Get-ChildItem *.csv | ForEach-Object { Get-Content $_ | Select-Object -Skip 1 } | Group-Object { $_ -split ',' | Select-Object -Index 0 } | ForEach-Object { $_.Group[0] } | Add-Content '%output_file%'" echo 处理完成!去重后的文件:%output_file%
关键说明:
Group-Object { $_ -split ',' | Select-Object -Index 0 }:这里是按CSV的第一列分组(去重依据),如果要按其他列,把Index 0改成对应列的索引(比如第二列就是Index 1)。$_.Group[0]:保留每组的第一条记录,如果你想保留最后一条,改成$_.Group[-1]即可。- PowerShell的
Get-Content对大文件的处理效率不错,1000万条记录完全能hold住。
注意事项
- 如果你的CSV字段包含逗号(用引号包裹的那种),
-split ','会拆分错误,这时候需要用更专业的CSV解析方式,比如PowerShell的Import-Csv:
这个方法更准确,但速度会稍慢一点,适合字段带特殊字符的场景。powershell -Command "Get-ChildItem *.csv | Import-Csv | Group-Object -Property '你的字段名' | ForEach-Object { $_.Group[0] } | Export-Csv '%output_file%' -NoTypeInformation" - 确保服务器有足够的临时磁盘空间,毕竟1000万条记录的临时文件体积不小。
内容的提问来源于stack exchange,提问作者pm1359
相关产品推荐
相关产品推荐

