自动化CSV文件合并和清理

时间:2016-01-08 21:22:04

标签: csv powershell batch-file merge

我不是一个代码人,并且花了一整天的时间试图完成这项任务而没有成功,希望我能从专家那里得到一些帮助。

我有一个名为Vehicles的文件夹,其中有两个子文件夹 - Automobiles and Trucks。每个子文件夹包含两个CSV文件,这些文件具有相同的(对于该子文件夹)标题/结构。 我想要完成的任务:

  1. 将Automobiles文件夹中的两个CSV文件合并而不复制标题,并将合并后的文件命名为Automobiles.csv
  2. 删除Automobiles.csv中第6列(标题为Fuel_Type)为" Diesel" (不带引号)然后将文件从子文件夹移动到主要的车辆文件夹。
  3. 将Trucks文件夹中的两个CSV文件合并而不复制标题并将合并文件命名为Trucks.csv
  4. 对于卡车文件夹中的合并文件,删除第6列(标题为" Fuel_Type")的所有行是" Diesel" (不带引号)然后将文件从子文件夹移动到主要的车辆文件夹。 显然,如果有人可以帮助1和2,我可以操纵3和4。
  5. BONUS POINTS :)获取Automobiles.csv和Trucks.csv文件,并使用Automobiles和Trucks标签创建Vehicles.xls文件。
  6. 很少有细节 - 文件非常大,每个CSV最多可以有35万行x 150列,每行大小为200 MB。我试图将删除标题放在一起的所有批处理脚本似乎都冻结了较大的文件。

    由于工作计算机上的用户权限,我们更倾向于使用Windows7 / 8原生的东西,并且不需要额外的软件,但如果没有可用的原生软件,则会考虑其他选项。

4 个答案:

答案 0 :(得分:0)

我将假设所有csv文件包含相同的标头信息,顺序相同。这就是我在powershell v2中的表现:

Function Merge-Vehicles 
{
param(
[string]$PathToCsv1,
[string]$PathToCsv2,
[string]$ExportPath
)   
$regex = "^(?:d|D)(?:i|I)(?:e|E)(?:s|S)(?:e|E)(?:l|L)$"
$CSV = Import-Csv $PathToCsv1
$CSV += Import-Csv $PathToCsv2
$CSV | Where-Object { ( $_.'Fuel_Type' -notmatch "$regex") } | Export-Csv -Path $ExportPath
}

首先,该函数将从用户定义的路径导入csv文件,并将导入的对象组合成一个数组。它将过滤属性'Fuel_Type'中不包含字符串“Diesel”的对象。剩余的对象将作为csv导出到用户定义的路径。

调用汽车的功能

Merge-Vehicles -PathToCsv1 C:\Vehicles\Autmobiles\csv1.csv -PathToCsv2 C:\Vehicles\Autmobiles\csv2.csv -ExportPath C:\Vehicles\Autmobiles.csv

对于卡车来说

Merge-Vehicles -PathToCsv1 C:\Vehicles\Trucks\csv1.csv -PathToCsv2 C:\Vehicles\Trucks\csv2.csv -ExportPath C:\Vehicles\Trucks.csv

我没有安装excel,所以我无法帮助创建工作簿。

答案 1 :(得分:0)

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\vehicles\automobiles"
SET "destdir=U:\vehicles"

FOR /f "usebackqdelims=" %%a IN ("%sourcedir%\file1.csv" "%sourcedir%\file2.csv") DO (
 ECHO(%%a>"%destdir%\vehicles.csv"
 ECHO(%%a>"%destdir%\vehicles_censored.csv"
 GOTO donehdrs
)
:donehdrs
FOR /f "skip=1tokens=1-6*usebackqdelims=," %%a IN ("%sourcedir%\file1.csv" "%sourcedir%\file2.csv") DO (
 ECHO(%%a,%%b,%%c,%%d,%%e,%%f,%%g>>"%destdir%\vehicles.csv"
 IF "%%f" neq "Diesel" ECHO(%%a,%%b,%%c,%%d,%%e,%%f,%%g>>"%destdir%\vehicles_censored.csv"
)
GOTO :EOF

您并未真正指出是否需要中间文件。

请注意,如果字段6之前的任何字段包含“包含逗号的带引号的字符串”,并且字段6之前的任何字段完全为空,则将正常工作(即。在data1,data2,,data4,data5,data6,data7

形式的行上

在没有检查过多可能性的情况下,信息不足以提高......

答案 2 :(得分:0)

简单地使用copy合并两个文件甚至可能更容易,然后使用编辑器删除多余的标题行。

答案 3 :(得分:0)

批处理文件本质上很慢,这在处理大型数据文件时很明显。我认为下面的方法是使用批处理文件执行此过程的最快方法。

@echo off
setlocal EnableDelayedExpansion

cd C:\Vehicles
call :MergeFiles Automobiles > Automobiles.csv
call :MergeFiles Trucks > Trucks.csv
goto :EOF


:MergeFiles

rem Enter to the given sub-folder (Automobiles or Trucks)
pushd %1

rem Process the (two) CSV files existent here
set "keepHeader=1"
for %%f in (*.csv) do (
   ECHO Procesing file: "%%~Ff" > CON
   call :ProcessFile < "%%f"
   set "keepHeader="
)

popd
exit /B


:ProcessFile

set /P "line="
if defined keepHeader echo(!line!

SET LINES=0

rem Reset errorlevel
ver > NUL
:loop
   set /P "line="
   if errorlevel 1 exit /B
   for /F "tokens=6 delims=," %%a in ("!line!") do (
      if "%%a" neq "Diesel" echo(!line!
   )

   REM Optional part: show progress
   SET /A "LINES+=1, MOD100=LINES%%100"
   IF %MOD100% EQU 0 ECHO Lines processed: %LINES% > CON

goto loop

注意:如果输入行大于1023个字符,则此方法失败,但相应于您的数据(文件中的35万行,大小为200 MB),每行约600个字节。