Board logo

标题: [文本处理] [已解决]批处理如何将多个文本按相同名称合并为单文本? [打印本页]

作者: w96692    时间: 2010-4-29 10:34     标题: [已解决]批处理如何将多个文本按相同名称合并为单文本?

在我的电脑“f”盘下“zhubi”文件夹内有名称为以下的,共计260个文本
内盘1.txt..............内盘31.txt
外盘1.txt..............外盘31.txt
内盘笔1.txt..............内盘笔31.txt
外盘笔1.txt..............外盘笔31.txt
委买1.txt..............委买31.txt
委卖1.txt..............委卖31.txt
委买笔1.txt..............委买笔31.txt
委卖笔1.txt..............委卖笔31.txt
内盘成交笔数.txt
内盘成交量.txt
内盘单笔最大成交量.txt
外盘成交笔数.txt
外盘成交量.txt
外盘单笔最大成交量.txt
委托买入总量.txt
委买总笔.txt
委买单笔最大成交量.txt
委托卖出总量.txt
委卖总笔.txt
委卖单笔最大成交量.txt
所有文本格式都一样,如以下,第一列为名称,第二列为日期,第三列为数值(所有第一列名称和第二列日期都一样,只有第三列数值不同)
SH600004 2010-04-28 37381
SH600005 2010-04-28 101010
SH600006 2010-04-28 36716
SH600007 2010-04-28 16350
SH600008 2010-04-28 45580
SH600009 2010-04-28 162257
SH600010 2010-04-28 83726
SH600011 2010-04-28 21314
SH600012 2010-04-28 67743
SH600016 2010-04-28 0
SH600017 2010-04-28 86413
SH600018 2010-04-28 55453
SH600019 2010-04-28 102978
SH600020 2010-04-28 25946
SH600021 2010-04-28 28294
SH600022 2010-04-28 53404
SH600026 2010-04-28 38750
SH600027 2010-04-28 0
SH600028 2010-04-28 197883
我想将这260个文件按第一列的名称合并成一个文件,我每天都用excel做同样的工作,太繁琐了,我想做个批处理,合并后文件格式如下(每列数值前为原始文本名称)
名称        日期    内盘1    内盘2   内盘3  内盘4.................
SH600004 2010-04-28 37381    16350    16350  16350.................
SH600005 2010-04-28 101010    5650    66350   350................
SH600006 2010-04-28 36716    5350    46350  616350................

[ 本帖最后由 w96692 于 2010-4-30 10:24 编辑 ]
作者: hanyeguxing    时间: 2010-4-29 17:27

是否按楼主在1楼提供的文本顺序进行合并?

以下批处理的文本处理顺序是按楼主提供的列表顺序进行:
  1. @echo off&setlocal enabledelayedexpansion
  2. set "a= "
  3. set "han=F:\zhubi\"
  4. set "ye=F:\zhubi\合并%date%.txt"
  5. set "gu=内盘成交笔数 内盘成交量 内盘单笔最大成交量 外盘成交笔数 外盘成交量 外盘单笔最大成交量 委托买入总量 委买总笔 委买单笔最大成交量 委托卖出总量 委卖总笔 委卖单笔最大成交量"
  6. for %%a in (内盘 外盘 内盘笔 外盘笔 委买 委卖 委买笔 委卖笔) do for /l %%b in (1,1,31) do call:xing "%%a%%b"
  7. for %%a in (%gu%) do call:xing "%%a"
  8. echo.开始合并到文本"%ye%"
  9. >"%ye%" echo.名称%a%日期!xing!
  10. for /f "usebackq tokens=1,2" %%a in ("%han%内盘1.txt") do >>"%ye%" echo.%%a%a%%%b!#%%a!
  11. echo.操作已完成&pause&exit
  12. :xing
  13. set "xing=!xing!%a%%~1"
  14. set "b=%han%%~1.txt"
  15. echo.正在预处理%b%...
  16. for /f "usebackq tokens=1,3" %%a in ("%b%") do set "#%%a=!#%%a!%a%%%b"
复制代码
说明:
本批处理正常运行可能受到此限制:最大单个环境变量大小为 8192 字节。所有变量的最大环境变量的总和大小(包括变量名和等号)为 65,536 KB。
变量a设置制表符为值,即set "a= "中的等号后面不是空格,是一个制表符
变量han设置文本所在目录路径,允许该路径存在空格。
变量ye设置合并后文本的路径和文件名。最后合并的文本名例如为“F:\zhubi\合并2010-04-29 星期四.txt”。
变量gu设置不循环的文本。

[ 本帖最后由 hanyeguxing 于 2010-4-30 00:10 编辑 ]
作者: w96692    时间: 2010-4-29 22:47

原帖由 hanyeguxing 于 2010-4-29 17:27 发表
是否按楼主在1楼提供的文本顺序进行合并?

以下批处理的文本处理顺序是按楼主提供的列表顺序进行:@echo off&setlocal enabledelayedexpansion
set "a= "
set "han=F:\zhubi\"
set "ye=F:\zhubi\合并%date%.tx ...

顺序就按我给出的就行(1-31)那样排列,无序号的文本放在末尾。
首先感谢您的帮助,可是不知为什么,运行代码后无任何反映(只出了一个黑框,无任何内容显示),也没有合并文件。
作者: sgaizxt001    时间: 2010-4-29 23:17

copy /b *.txt  a.txt 可以把这些文本里的所有内容合并到a.txt,但是好象前缀都一样啊。比如:
内盘笔4
SH600000        2010-04-29        1935
SH600004        2010-04-29        324
SH600005        2010-04-29        1020
SH600007        2010-04-29        65
SH600008        2010-04-29        443
SH600009        2010-04-29        1907
SH600010        2010-04-29        676
SH600011        2010-04-29        156
委买1
SH600000        2010-04-29        265273
SH600004        2010-04-29        35524
SH600005        2010-04-29        142144
SH600007        2010-04-29        9673
SH600008        2010-04-29        47285
SH600009        2010-04-29        238261
SH600010        2010-04-29        129699
SH600011        2010-04-29        18959

关键是第3列要怎么弄?
作者: hanyeguxing    时间: 2010-4-29 23:34

测试2楼的代码没有问题:
1,由于原先未加入进度显示,造成缺乏实时显示状态。针对这个问题,已对2楼代码进行修改。
2,随着变量的处理量变大,速度会越来越慢。实际测试,完成整个操作需要24分50秒。
3,优点是不使用临时文件。
4,按指定的文本顺序进行处理。

[ 本帖最后由 hanyeguxing 于 2010-4-30 00:50 编辑 ]
作者: namejm    时间: 2010-4-30 00:34

  看了楼主的描述,楼主的需求似乎是这样的:
  1、有260个文本文件,每个文件有3列数据;
  2、在这些文本文件中,每个文件对应行上的第1列和第2列数据相同;
  3、需要把这260个文件中的所有数据都汇总到一个文件中,从第3列起,每列字段以文件名作为字段名,以对应行上第3列的数据作为相应列字段的数据加以保存;
  4、第3列起的列字段顺序,以文件名中1~31的升序排列,文件名前缀相同的放一块,没有相同前缀的放后面;

  如果我这个描述准确、完整地归纳了楼主的意思的话,可以使用下面的代码生成中间数据,然后导入excel中加以处理:
  1. @echo off
  2. set t=%time%
  3. (
  4. set /p=名称 日期<nul
  5. for %%i in (*.txt) do set /p =%%~ni<nul
  6. echo.
  7. for /f "tokens=1,2" %%i in (委买1.txt) do (
  8.     echo 正在处理 %%i>con
  9.     set /p=%%i %%j<nul
  10.     for /f "tokens=3" %%x in ('findstr /bc:"%%i" *.txt') do set /p=%%x<nul
  11.     echo.
  12. )
  13. echo.
  14. )>result
  15. start notepad.exe result
  16. cls
  17. echo 处理完毕
  18. echo %t%
  19. echo %time%
  20. pause
复制代码
  以上代码需放在F盘Zhubi目录下运行,思路是:

  1、用 for 语句读取当前目录下的所有 txt 文件名,生成行标题;
  2、根据 委买1.txt 文件里第1列的数据,在所有txt文件中查找以 委买1.txt 文件中第1列数据打头的对应行上第3列的数据,拼接起来,作为新行保存。只要保证每个文件对应行上的第1列和第2列绝对相同,没有丝毫错位,则 委买1.txt 可以换成任意一个存在的文本文件名,实际上,这也是本代码能够实现楼主意图的前提。

  通过以上代码,生成的数据保存在名为result的文本文件中,每列数据以空格分隔。考虑到批处理中每行能处理的最大字节数有限制(约为8192字节),所以每列数据以单个空格分隔,这样,假设每列数值在10字符以内,则每个数值行的长度约为(262*10+261)字节,而标题行的字符数可能是数值行长度的1.5倍,单行数据长度不会超限。

  需要注意的是,数据处理结果文件绝对不能保持为.txt后缀,否则,会导致重复统计。

  另外,当文件名的序号超过9的时候,最终结果的字段名不能完全按照1~31这样的升序排列,而是按照1,10~19,2,20~29,3,30,31这样的顺序排列,需要在excel中自行调整顺序。

  导入excel时,请以空格作为分隔符号切分文本。

  在本人机器上的测试结果,用楼主提供的12个文本,耗时3分钟左右,照此速度推测,260个文件约需1小时左右。本人机器配置为:主频1.6GHz、512M内存,SP3系统。
作者: sgaizxt001    时间: 2010-4-30 07:32

哦,明白你的意思了。不过楼上的代码已经够精简了,不继续丢人了
作者: w96692    时间: 2010-4-30 07:51

首先感谢大家的帮助,我的求助本意是做个批处理不用每次都复制到文件夹执行,(日复一日也挺麻烦的),版主的很好,就是也需要复制到文件夹内,如果能指定目录就好了

[ 本帖最后由 w96692 于 2010-4-30 08:21 编辑 ]
作者: w96692    时间: 2010-4-30 08:11     标题: 回复 6楼 的帖子

用了您的代码,也很快处理完,但是也需要复制,如果能够不用复制就好了(我每天只处理f盘zhubi文件夹,这是固定的),谢谢您

[ 本帖最后由 w96692 于 2010-4-30 08:19 编辑 ]
作者: more    时间: 2010-4-30 09:19

能用excel完成的就用excel吧,效率不在同一个级别上...
作者: namejm    时间: 2010-4-30 10:03

  修改一下6楼的代码,使得批处理可以放在任意位置,但是要处理的目录除外(可以放在要处理目录的子目录下),并且,生成的结果保存在批处理文件当前目录下:
  1. @echo off
  2. set t=%time%
  3. set "olddir=%cd%"
  4. cd /d f:\zhubi
  5. (
  6. set /p=名称 日期<nul
  7. for %%i in ( *.txt) do set /p =%%~ni<nul
  8. echo.
  9. for /f "tokens=1,2" %%i in (委买1.txt) do (
  10.     echo 正在处理 %%i>con
  11.     set /p=%%i %%j<nul
  12.     for /f "tokens=3" %%x in ('findstr "%%i" *.txt') do set /p=%%x<nul
  13.     echo.
  14. )
  15. echo.
  16. )>"%olddir%\result.txt"
  17. start "" "%olddir%\result.txt"
  18. cls
  19. echo 处理完毕
  20. echo %t%
  21. echo %time%
  22. pause
复制代码
  再来一个略为提高速度的代码,但是需要生成临时文件,该代码的思路是先把所有文本合并到一个临时文件中,然后读取该临时文件的内容,从而避免读取多个文件,使得速度略有提升:
  1. @echo off
  2. set "olddir=%cd%"
  3. cd /d f:\zhubi
  4. set t=%time%
  5. cd.>"%olddir%\tmp.txt"
  6. for %%i in (*.txt) do (
  7.     call set str1=%%str1%%+%%i
  8.     call set str2=%%str2%% %%~ni
  9. )
  10. copy %str1:~1% "%olddir%\tmp.txt"
  11. echo 名称 日期 %str2%>"%olddir%\result.txt"
  12. cls
  13. (for /f "tokens=1,2" %%i in (委买1.txt) do (
  14.     echo 正在处理 %%i>con
  15.     set /p=%%i %%j<nul
  16.     for /f "tokens=3" %%x in ('findstr /ib "%%i" "%olddir%\tmp.txt"') do (
  17.         set /p=%%x<nul
  18.     )
  19.     echo.
  20. ))>>"%olddir%\result.txt"
  21. start "" "%olddir%\result.txt"
  22. cls
  23. echo 处理完毕
  24. echo %t%
  25. echo %time%
  26. pause
复制代码

作者: w96692    时间: 2010-4-30 10:24

原帖由 namejm 于 2010-4-30 10:03 发表
  修改一下6楼的代码,使得批处理可以放在任意位置,但是要处理的目录除外(可以放在要处理目录的子目录下),并且,生成的结果保存在批处理文件当前目录下:@echo off
set t=%time%
set "olddir=%cd%"
cd /d f ...
谢谢管理员,虽然比excel慢点,但省事了,我是又笨又懒啊,再次感谢
作者: w96692    时间: 2010-4-30 10:26

原帖由 more 于 2010-4-30 09:19 发表
能用excel完成的就用excel吧,效率不在同一个级别上...

是啊,excel处理所有文件也就20秒,批处理需要几分钟啊,但省事好多,谢谢大家!!!!
作者: namejm    时间: 2010-4-30 10:31

  用vba写一段excel宏应当能满足楼主的懒惰需求,可惜我不会写vba,不知有谁愿意尝试一下。
作者: more    时间: 2010-5-2 07:04

如果要做成Excel的话,本人愿意一试...否则用vbs,效率也比批处理高得多.

[ 本帖最后由 more 于 2010-5-2 07:34 编辑 ]
作者: more    时间: 2010-5-2 12:43

帖个VBA的.
  1. Option Explicit
  2. Sub Try()
  3.     Dim lngRow As Long, i As Integer, objFso As Object, objFolder As Object, arrData, _
  4.         objFl As Object, objOpFl As Object, strPth As String, intCol As Integer, strTime As String, intSh As Integer
  5.     strPth = "f:\zhubi"     '在此指定要处理的目标文件夹
  6.     Set objFso = CreateObject("scripting.filesystemobject")
  7.     If objFso.folderexists(strPth) = False Then
  8.         MsgBox "文件夹" & Chr(34) & strPth & Chr(34) & "不存在!!!" & Chr(10) & vbCrLf & _
  9.             "请按 Alt + F11 打开 VBE 编辑器指定新的路径...", 48, " :("
  10.         Set objFso = Nothing
  11.         Exit Sub
  12.     End If
  13.     strTime = Time
  14.     intSh = 1
  15.     Sheets(intSh).Select
  16.     Application.ScreenUpdating = False
  17.     Range("a1:iv65536").ClearContents
  18.     Cells(1, 1) = "名称": Cells(1, 2) = "日期"
  19.     Set objFolder = objFso.getfolder(strPth)
  20.     Set objOpFl = objFso.opentextfile(strPth & "\" & "内盘笔4.txt", 1)
  21.     lngRow = 1: intCol = 2
  22.     Do Until objOpFl.atendofstream
  23.         arrData = Split(objOpFl.readline, vbTab, -1, 1)
  24.         lngRow = lngRow + 1
  25.         Cells(lngRow, 1) = arrData(0): Cells(lngRow, 2) = arrData(1)
  26.     Loop
  27.     objOpFl.Close
  28.     For Each objFl In objFolder.Files
  29.         If objFso.GetExtensionName(strPth & "\" & objFl.Name) = "txt" Then
  30.             Set objOpFl = objFso.opentextfile(strPth & "\" & objFl.Name)
  31.             lngRow = 1: intCol = intCol + 1
  32.             If intCol > 256 Then
  33.                 intCol = 1: intSh = intSh + 1
  34.                 For i = 1 To 256
  35.                     Columns(i).AutoFit
  36.                 Next i
  37.                 Sheets(intSh).Select
  38.             End If
  39.             Cells(1, intCol) = objFso.GetbaseName(objFl.Name)
  40.             Do Until objOpFl.atendofstream
  41.                 arrData = Split(objOpFl.readline, vbTab, -1, 1)
  42.                 lngRow = lngRow + 1
  43.                 Cells(lngRow, intCol) = arrData(2)
  44.             Loop
  45.             objOpFl.Close
  46.         End If
  47.     Next
  48.     Set objFso = Nothing: Set objFolder = Nothing: Set objOpFl = Nothing
  49.     For i = 1 To Range("iv1").End(xlToLeft).Column
  50.         Columns(i).AutoFit
  51.     Next i
  52.     Application.ScreenUpdating = True
  53.     MsgBox strTime & vbCrLf & Time & Chr(10) & "Done!", 0, "Right?"
  54. End Sub
复制代码
在本机上就楼主上传的附件,用namejm的批代码要几分钟时间,而VBA仅一两秒钟,效率简直一个天一个地...

代码贴错了,改一改...
作者: 随风    时间: 2010-5-2 22:57

又是一个挑战效率的文本题
想起好像有个 Hitme 前辈,
初学批处理时看到他的代码经常使用大量的临时文件来完成任务,现也模仿下 ^_^
我理解题意为:结果文件将会有262列,每列为某单个文件的第3列
思路:
  先生成260个临时文件,以文本的第1、2列为文件名,第3列为内容
  再将所有文件合为一个文件,将单个文件的所有内容合为一行即可
  
创建测试环境太麻烦,故代码未经测试,只是想当然 ^_^
若楼主回头看见此帖,还请测试后回复一下结果是否正确,且耗时如何。
此代码只有针对性没有通用性,是专对楼主题意解的。
  1. @echo off
  2. set var=内盘 外盘 内盘笔 外盘笔 委买 委卖 委买笔 委卖笔
  3. md tem
  4. for %%i in (%var%) do (
  5.    for /l %%L in (1 1 31) do (
  6.       for /f "tokens=1-3" %%a in (%%i%%L.txt) do >>"tem\%%a %%b.txt" echo %%c
  7.     )
  8. )
  9. set num=内盘成交笔数 内盘成交量 内盘单笔最大成交量 外盘成交笔数 外盘成交量 外盘单笔最大成交量
  10. set num=%num% 委托买入总量 委买总笔 委买单笔最大成交量 委托卖出总量 委卖总笔 委卖单笔最大成交量
  11. set /p=名称 日期 %var% %num%<nul>test.txt
  12. for %%i in (%num%) do (
  13.    for /f "tokens=1-3" %%a in (%%i.txt) do >>"tem\%%a %%b" echo %%c
  14. )
  15. set lj=%cd%
  16. cd/d tem
  17. for %%i in (*.txt) do (
  18.    set/p=%%~ni<nul>>"%lj%\test.txt"
  19.    for /f "usebackq delims=" %%a in ("%%i") do set /p= %%a<nul>>"%lj%\test.txt"
  20.    echo;
  21. )
  22. cd..
  23. rd /s /q tem
  24. start test.txt
复制代码

[ 本帖最后由 随风 于 2010-5-3 18:04 编辑 ]
作者: w96692    时间: 2010-5-3 14:01

原帖由 more 于 2010-5-2 12:43 发表
帖个VBA的.Option Explicit

Sub Try()
    Dim lngRow As Long, i As Integer, objFso As Object, objFolder As Object, arrData, _
        objFl As Object, objOpFl As Object, strPth As String, intCol As ...

感谢关注,附上测试结果,excel2007运行19秒完成所有文件,还未看正确性,就效率而言,牛!!!!!

[ 本帖最后由 w96692 于 2010-5-3 14:02 编辑 ]
作者: w96692    时间: 2010-5-3 14:13

原帖由 随风 于 2010-5-2 22:57 发表
又是一个挑战效率的文本题
想起好像有个 Hitme 前辈,
初学批处理时看到他的代码经常使用大量的临时文件来完成任务,现也模仿下 ^_^
我理解题意为:结果文件将会有262列,每列为某单个文件的第3列
思路:
  先生 ...
我看您理解的意思也对,但代码不能运行,不知何故?(放到别的盘下运行出一个有表头的txt文本,放到zhubi文件夹下不运行)




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2