我这里有一个文件file1.txt,内容将是这样的
013A Not Visible ???:? 09C:DB 2-Way Mir N/Grp'd RW 3 013B Not Visible ???:? 07A:DB 2-Way Mir N/Grp'd RW 3 013C Not Visible ???:? 08B:DB 2-Way Mir N/Grp'd RW 3 0242 Not Visible ???:? 10D:D3 RAID-5 N/Grp'd (M) RW 43163 0246 Not Visible ???:? 10A:CB RAID-5 N/Grp'd (M) RW 43163 024E Not Visible ???:? 09D:D4 RAID-5 N/Grp'd (M) RW 43163 02A6 Not Visible ???:? 06B:C8 RAID-5 N/Grp'd (M) RW 43163 09A8 Not Visible ???:? 07C:D1 RAID-6 N/Grp'd (M) RW 43163 09AA Not Visible ???:? 09D:C1 RAID-6 N/Grp'd (M) RW 43163 09AC Not Visible ???:? 09A:C2 RAID-6 N/Grp'd (M) RW 43163 09B0 Not Visible ???:? 08B:C0 RAID-6 N/Grp'd (M) RW 43163
我的任务是在上面用粗体字母显示的列中搜索单词,并获得每个类别的最后一列中的数字总和。
在上面的示例中我有3组单词
所以我需要总结最后一列。对于2-Way Mir
,总和为3+3+3= 9
。
如何使用批处理文件收集相同的内容?
实际间距:
答案 0 :(得分:1)
GNU代码awk:
>awk "{a[$6]+=$NF} END {for (x in a) print x,a[x]}" file RAID-5 172652 2-Way 9 RAID-6 172652
为方便起见,请将Mir
添加到2-Way
!
Download here
答案 1 :(得分:0)
@ECHO OFF
SETLOCAL
FOR %%i IN (mir2 raid5 raid6) DO SET /a %%i=0
FOR /f "delims=" %%i IN (file1.txt) DO CALL :process %%i
ECHO 2-Way Mir : %mir2%
ECHO RAID-5 : %raid5%
ECHO RAID-6 : %raid6%
GOTO :EOF
:process
SET "line=%*"
:loop
SET value=%2
IF DEFINED value shift&GOTO loop
SET line=%line:~38,9%
IF /i "%line%"=="2-way mir" SET /a mir2+=%1
IF /i "%line%"=="RAID-5 " SET /a raid5+=%1
IF /i "%line%"=="RAID-6 " SET /a raid6+=%1
GOTO :EOF
应该为你做的工作。我假设围绕键串的星号是尝试使这些字符串变粗的失败。我还假设数据采用固定列格式。实际上,如果确实如此,可能会有更简单的方法:
@ECHO OFF
SETLOCAL
FOR %%i IN (mir2 raid5 raid6) DO SET /a %%i=0
FOR /f "delims=" %%i IN (file1.txt) DO CALL :process %%i
ECHO 2-Way Mir : %mir2%
ECHO RAID-5 : %raid5%
ECHO RAID-6 : %raid6%
GOTO :EOF
:process
SET "line=%*"
IF /i "%line:~38,9%"=="2-way mir" SET /a mir2+=%line:~70%
IF /i "%line:~38,9%"=="RAID-5 " SET /a raid5+=%line:~70%
IF /i "%line:~38,9%"=="RAID-6 " SET /a raid6+=%line:~70%
GOTO :EOF
如果需要可以进一步简化。请注意,9
语句中的if
长度必须匹配,而/i
会使if
不区分大小写。
扩展匹配 - 稍微复杂一些,但会自动调整......
@ECHO OFF
SETLOCAL
FOR /f "delims==" %%i IN ('set $ 2^>nul') DO SET "%%i="
SET maps="2-way mir" "RAID-5 "
SET maps=%maps% "RAID-6 "
SET strcnt=0
FOR %%i IN (%maps%) DO CALL :setup %%i
FOR /f "delims=" %%i IN (file1.txt) DO CALL :process %%i
SET mapnbr=1
:ploop
CALL ECHO %%$_%mapnbr%%% : %%$%mapnbr%%%
SET /a mapnbr+=1
IF %mapnbr% leq %strcnt% GOTO ploop
GOTO :EOF
:process
SET "line=%*"
SET mapnbr=%strcnt%
:matchloop
CALL SET match=%%$_%mapnbr%%%
IF /i "%line:~38,9%"==%match% CALL SET /a $%mapnbr%+=%line:~70%&GOTO :eof
SET /a mapnbr-=1
IF %mapnbr% neq 0 GOTO matchloop
GOTO :EOF
:: Set $n=0 & $_n=string-to-match
:setup
SET /a strcnt+=1
SET /a $%strcnt%=0
SET $_%strcnt%=%1
GOTO :eof
基本上,变量$n
包含要在引号中匹配的字符串$_n
。只需将带引号的9个字符的字符串添加到带有空格或逗号分隔符的maps
中。
答案 2 :(得分:0)
批量数学限制使得如果任何总和超过2147483647,则无法创建合理的纯批处理解决方案。可以编写复杂的例程来批量执行大量计算,但我不认为它们是合理的。
假设所有总和都小于允许的最大值,则以下解决方案有效。
如果你的“单词”不包含空格,这将会容易得多。通常,环境变量可以在名称中包含空格。但SET / A选项不支持变量名中的空格。因此,需要一组额外的映射变量来将每个唯一的“单词”映射到不包含空格的变量名称。如果“单词”从不包含空格,则运行总和可以简单地存储在直接从“单词”派生的变量中。
@echo off
setlocal enableDelayedExpansion
:: Define input file
set "file=file1.txt"
:: Clear any existing $ variables and initialize unique "word" count
for /f "delims==" %%V in ('2^>nul set $') do set "%%V="
set "cnt=0"
:: Iteratively read each line in the file
for /f "usebackq delims=" %%A in ("%file%") do (
%= Extract the correct "word" (%%N) from the line by position =%
set "ln=%%A"
for /f "delims=" %%N in ("!ln:~42,13!") do (
%= If this is a new "word", then setup mapping =%
if not defined $%%N (
set /a cnt+=1 %= Increment unique "word" count =%
set "$%%N=!cnt!" %= Map "word" to an "array" position =%
set "name!cnt!=%%N" %= Store "word" in name "array" =%
)
%= Extract the value from line by position and add it to =%
%= the appropriate array element by using the $word map =%
set /a "val!$%%N!+=!ln:~71!"
)
)
:: Iterate the "arrays" and print results
for /l %%N in (1 1 %cnt%) do echo !name%%N! !val%%N!
注意:上面的代码使用环境变量名称约定来模拟数组。批处理没有真正的数组。
以下是file1.txt中的示例数据的结果:
2-Way Mir 9
RAID-5 172652
RAID-6 172652