【问题标题】:Merge several csv file side by side using batch file使用批处理文件并排合并多个 csv 文件
【发布时间】:2015-05-05 04:31:00
【问题描述】:

我正在寻找两个将几个 csv 文件合并为一个。但是我需要它们合并,以便列并排而不是继续。 我的文件每次都有两列,通过提取每个文件的第二列并复制到另一列,我将得到一个 csv 文件,这样我将得到一个包含 x 列的文件(第二列)。

例如

文件1

A B
1 2
1 2
1 2

文件2

A C
1 3
1 3
1 3

文件

A X
1 x
1 x
1 x

结果

B C X
2 3 x
2 3 x
2 3 x

我发现了这个:Merge csv file side by side using batch file

但它只适用于两个文件,它不会提取任何内容。

谢谢。

【问题讨论】:

    标签: csv batch-file merge


    【解决方案1】:

    原来在this post描述的方法可以修改,以便处理可变数量的文件(最多8个),所以你只需要将所需的文件放在参数中:

    @echo off
    setlocal DisableDelayedExpansion
    
    rem MergeFiles.bat: Merge several files horizontally
    rem Antonio Perez Ayala
    
    rem Process files in the arguments and 
    rem assemble the lists of redirections and SET /P commands
    set file1=%1
    set "redirs="
    set "commands="
    set n=2
    :nextFile
       shift
       if "%~1" equ "" goto endFiles
       set /A n+=1
       set "redirs=%redirs% %n%<%1"
       set "commands=%commands% & set /P "part=!part:* =! " <&%n%"
    goto nextFile
    :endFiles
    
    rem First file is read with FOR /F command
    rem The rest of files are read via standard handles, starting at # 3
    
    %redirs% (
       for /F "usebackq delims=" %%a in (%file1%) do (
          rem Get first part from first file
          set "part=%%a"
          rem Output parts from all files, excepting the last one
          setlocal EnableDelayedExpansion
          %commands:~3%
          rem Output part from last file
          echo !part:* =!
          endlocal
       )
    ) > result.txt
    

    例如:

    C:\> type file?.txt
    
    file1.txt
    
    A B
    1 2
    1 2
    1 2
    
    file2.txt
    
    A C
    1 3
    1 3
    1 3
    
    fileX.txt
    
    A X
    1 x
    1 x
    1 x
    
    fileY.txt
    
    A Y
    1 y
    1 y
    1 y
    
    C:\> MergeFiles.bat file1.txt file2.txt fileX.txt fileY.txt
    
    C:\> type result.txt
    B C X Y
    2 3 x y
    2 3 x y
    2 3 x y
    

    【讨论】:

      【解决方案2】:

      以下所有解决方案均假定所有输入文件的格式一致且行数相同。

      Merge csv file side by side using batch file 使用的技术可以修改为解析和支持超过 2 个文件。我还在循环中打开和关闭延迟扩展,以保护可能出现在数据中的任何!。如果在启用延迟扩展的情况下扩展包含! 的 FOR 变量,则会损坏:

      @echo off
      setlocal disableDelayedExpansion
      3<"test2.txt" 4<"test3.txt" (
        for /f "usebackq tokens=2 delims= " %%A in ("test1.txt") do (
          set "A=%%A"
          set /p "B=" <&3
          set /p "C=" <&4
          setlocal enableDelayedExpansion
          echo !A! !B:* =! !C:* =!
          endlocal
        )
      ) >"result.txt"
      

      使用 FOR 循环加上句柄 0 和 3-9,可以将上述内容扩展到最多支持 9 个输入文件。如果您有超过 8 个输入,那么您需要多个循环。第一个循环可以处理前 9 个文件并将部分结果写入临时文件。连续循环可以从临时文件中读取并合并多达 8 个附加文件。

      如果你的解析规则变得更复杂,上面可能会变得很麻烦。

      我的JREPL.BAT hybrid JScript/batch utility可用于高效地解析和合并任意数量的文件,您可以根据需要修改正则表达式以解析几乎任何csv文件格式。

      @echo off
      setlocal
      set "merge=jrepl ".*( .*)" "stdin.ReadLine()+$1" /j /f"
      jrepl ".* (.*)" "$1" /f test1.txt | %merge% test2.txt | %merge% test3.txt >result.txt
      

      理论上你可以使用任意数量的管道来支持你所有的输入文件,但是如果你得到太多,它可能会变得低效。您可以使用临时文件来暂存合并以保持效率。

      【讨论】:

        【解决方案3】:
        @ECHO OFF
        SETLOCAL enabledelayedexpansion
        :: remove variables starting $
        FOR  /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
        SET /a $count=0
        FOR %%a IN (q28850167*.txt) DO (
         FOR  /f "tokens=1,2*delims=: " %%b IN ('findstr /n /r "^" "%%a"') DO (
          SET $%%b=!$%%b! %%d
          IF !$count! LSS %%b SET /a $count=%%b
         )
        )
        (
        FOR /L %%a IN (1,1,%$count%) DO ECHO(!$%%a:~1!
        )>newfile.txt
        
        
        GOTO :EOF
        

        我使用包含您的数据的名为 q28850167*.txt 的文件进行测试。
        生成 newfile.txt

        清除所有以$开头的变量

        对于每个匹配掩码的文件,通过findstr/n 处理每一行以将number : 应用于每行的开头。使用:Space 作为分隔符选择第一列和第三列,并附加到变量$linenumber 跟踪$count 中的最高行号。

        然后简单地从存储的数据中复制每一行。

        【讨论】:

        • 文件名可能没有按正确的列顺序排序,在这种情况下,您可以在外部 FOR 循环中以正确的顺序显式列出每个文件 - for .... in ( file1 file2 file3 ) do (
        猜你喜欢
        • 2014-03-31
        • 2020-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-08
        • 2015-06-28
        相关资源
        最近更新 更多