批处理 - 读取和汇总来自不同TXT文件的值

时间:2016-04-13 14:59:04

标签: batch-file text cmd

我有一个包含一些txt.files的文件夹,例如

FILE1.TXT:

'NumberOfEntries'|'TotalAmount1'|'TotalAmount2'
'10'|'150250.02'|'327535.49'

FILE2.TXT:

'NumberOfEntries'|'TotalAmount1'|'TotalAmount2'
'15'|'327551.09'|'18761432.56'

File3.txt:

'NumberOfEntries'|'TotalAmount1'|'TotalAmount2'
'20'|'100000.44'|'220030.90'

依旧......

我需要的是总结它,保持标题并将第二行的值相加,得到这样的结果:

FileALL.txt:

'NumberOfEntries'|'TotalAmount1'|'TotalAmount2'
'45'|'577801.55'|'19308998.95'

我需要这是通用的,对于其他类型的标题,对于具有更多或更少列的文件等都是必需的。

到目前为止,我设法从第一个文件中获取标题,但其余的我有点卡住了:

del "%CD%\%year%\ALL\fileALL.txt"   
for /f "tokens=* delims=" %%a in (%year%\folder\file_01.txt) do (
    echo %%a >> "%CD%\%year%\ALL\fileALL.txt"
    goto _ExitForLoop
    )
:_ExitForLoop

for %%F in (%year%\folder\*.txt) do (
  set /a total1=0
  set /a total2=0
  set /a total3=0
  for /f "usebackq tokens=1 delims=|" %%a in ("%%F") do set /a total1+=%%a
  for /f "usebackq tokens=2 delims=|" %%b in ("%%F") do set /a total2+=%%b
  for /f "usebackq tokens=3 delims=|" %%c in ("%%F") do set /a total3+=%%c
  echo %total1%|%total2%|%total3% > "%CD%\%year%\ALL\fileALL.txt"
)
exit /b

2 个答案:

答案 0 :(得分:3)

@echo off
setlocal EnableDelayedExpansion

rem Read the header and get the number of columns from it
for %%F in (*.txt) do set /P "header=" < %%F & goto ExitForLoop
:ExitForLoop
set "cols=0"
set "line=%header%"
:nextCol
   for /F "tokens=1* delims=|" %%a in ("%line%") do (
      set /A cols+=1
      set "line=%%b"
   )
if defined line goto nextCol

rem Initialize the array of totals
for /L %%i in (1,1,%cols%) do set "total[%%i]=0"

for %%F in (*.txt) do (
   for /F "usebackq skip=1 delims=" %%L in ("%%F") do (
      set "line=%%L"
      for /L %%i in (1,1,%cols%) do (
         for /F "tokens=1* delims=|" %%a in ("!line!") do (
            set "col=%%a"
            set "col=!col:'=!"
            set /A "total[%%i]+=!col:.=!"
            set "line=%%b"
         )
      )
   )
)

rem Show totals
< NUL (
   echo !header!
   for /L %%i in (1,1,%cols%) do (
      if %%i equ 1 (
         set /P "='!total[%%i]!'"
      ) else (
         set /P "=|'!total[%%i]:~0,-2!.!total[%%i]:~-2!'"
      )
   )
   echo/
) > fileALL.txt

输出:

'NumberOfEntries'|'TotalAmount1'|'TotalAmount2'
'45'|'577801.55'|'19308998.95'

备注:

  • 如果任何文件的数据列数较少,则此程序将失败。
  • 如果2中的任何数据列没有精确两位小数,结果将是错误的。

答案 1 :(得分:1)

Batch没有本机浮点支持,并且可靠地解析文本通常很不方便。

您可以使用我的JREPL.BAT regular expression find/replace utility通过一些用户提供的JScript有效地解决此问题。 JREPL.BAT是纯脚本(混合JScript /批处理),可以在XP之后的任何Windows机器上本机运行。

以下解决方案使用问题中列出的确切格式。它假定所有行都具有正确的列数,并且每个字段都有一个值。它还假定每个文件的最后一行由\r\n\n终止。

代码很长。我使用^行继续来使代码更容易阅读。

type "%year%\folder\*.txt" 2>nul|jrepl ^
  "^'(\d+)'\|'(\d*\.?\d*)'\|'(\d*\.?\d*)'$ ^.+"^
  "a+=parseInt($2);b+=parseFloat($3);c+=parseFloat($4);false h=$0;false"^
  /jbeg "var h,a=0,b=0,c=0; function r(n){return Math.round(n*100)/100}"^
  /jend "output.WriteLine(''+h+'\r\n\''+a+'\'|\''+r(b)+'\'|\''+r(c)+'\'')"^
  /t " " /jmatch /o "%year%\ALL\fileALL.txt"

type命令将每个文件合并为一个数据流,这就是每个文件必须以\n结尾的原因。输出通过管道传输到JREPL,完成剩下的工作。

/jmatch选项将替换字符串视为已计算的JScript表达式,并仅输出匹配的替换值。

/t " "选项将搜索和替换字符串视为一组空格分隔的字符串。第一个搜索字符串由第一个替换字符串替换,第二个搜索字符串由第二个替换字符串替换,等等。

/o选项指定输出文件。

/jbeg选项定义并初始化变量以保存标头记录以及三个聚合列值。它还定义了一个将浮点数舍入到两个小数位的函数。需要舍入,因为浮点数不能准确表示数字。

第一个搜索字符串(捕获为$1)与数据行匹配,并捕获$2$3$4中的每个字段值。相应的替换JScript字符串解析值并将它们添加到聚合值。它返回false以禁用任何正常输出。

第二个搜索字符串(捕获为$5)匹配第一个未匹配的整行。如果文件格式正确,那么这将始终是标题记录。替换JScript字符串只是将匹配的字符串($0始终表示整个匹配的字符串)存储在标头变量中,并返回false以禁用输出。最后一个标题找到了“胜利”,但我认为它们都是一样的。

最后,/jend选项是终结代码,用于写出标题行和最终聚合值行,并进行适当的舍入。