如何在日志文件中查找子字符串并使用dos批处理文件递增计数器

时间:2014-02-21 13:25:33

标签: string batch-file token dhcp

任何人都可以帮我制作Windows批处理文件,以便从日志文件中找到子字符串。 log.log文件的示例如下所示

ID,Date,Time,Description,IP Address,Host Name,MAC Address
10,02/21/14,00:29:45,Assign,172.20.55.50,PC1,123456789AB1,
31,02/21/14,00:29:45,DNS Update,172.20.55.50,PC1,123456789AB1,
10,02/21/14,00:29:45,Assign,172.30.55.50,PC2,123456789AB2,
31,02/21/14,00:29:45,DNS Update,172.30.55.50,PC1,123456789AB2,
10,02/21/14,00:29:45,Assign,172.20.56.60,PC3,123456789AB3,
10,02/21/14,00:29:45,Assign,172.30.55.60,PC4,123456789AB4,
**11,02/21/14,00:30:45,Assign,172.30.55.10,PC2,123456789AB5,**
**11,02/21/14,00:30:46,Assign,172.30.55.10,PC2,123456789AB5,**
**31,02/21/14,00:00:37,DNS Update Failed,172.17.110.13,TAR-CAR-051180L.WTPK.local,-1,**

这基本上是DHCP日志文件。目标是计算新分配IP请求的数量(其ID为10)和更新IP请求的数量(其ID为11)。

对于ID 10,如果IP以172.20.55或172.20.56开头,则应在计数器“NewPoolA”中递增,如果IP以172.30.55或172.30.56开始,则应在“NewPoolB”中递增。 / p>

类似于ID 11,如果IP以172.20.55或172.20.56开头,它应该在计数器“RenewPoolA”中递增,如果IP以172.30.55或172.30.56开始,它应该在“RenewPoolB”中递增。 / p> 到目前为止,我所做的是在

之下
@echo off 
Setlocal EnableDelayedExpansion

set /a NewPoolA=0
set /a NewPoolB=0
set /a RenewPoolA=0
set /a RenewPoolB=0

for /F "tokens=1-6 delims=," %%a in (log.log) do (
    if %%a equ 10 (
        rem if %%e contains 172.20.55 (
            set /a NewPoolA += 1
            goto someLabel
        )
        rem else if %%e contains 172.20.56 (
            set /a NewPoolA += 1
            goto someLabel
        )
        rem else if %%e contains 172.30.55 (
            set /a NewPoolB += 1
            goto someLabel
        )
        rem else if %%e contains 172.30.56 (
            set /a NewPoolB += 1
            goto someLabel
        )
        rem -------- if id 10 and not match any condition then
        goto someLabel
    ) else if %%a equ 11 (
        rem if %%e contains 172.20.55 (
            set /a RenewPoolA += 1
            goto someLabel
        )
        rem else if %%e contains 172.20.56 (
            set /a RenewPoolA += 1
            goto someLabel
        )
        rem else if %%e contains 172.30.55 (
            set /a RenewPoolB += 1
            goto someLabel
        )
        rem else if %%e contains 172.30.56 (
            set /a RenewPoolB += 1
            goto someLabel
        )
        rem -------- if id 11 and not match any condition then
        goto someLabel
    )
)
echo Total new request in Pool A is %NewPoolA%
echo Total renewal request in Pool A is %RenewPoolA%

echo Total new request in Pool B is %NewPoolB%
echo Total renewal request in Pool B is %RenewPoolB%

这是逻辑和我的理解,它将如何运作。我不知道dos批处理命令的语法。

这两个池只是一个例子。我有80个游泳池,我必须这样做。在日志文件中有近100,000个条目。要将这个行数与每个池相匹配将花费太多时间。因此,目标是在递增值后跳出“if条件”并缩短批处理文件的执行时间。

另外一件事,日志文件包含相同mac地址的不同时间的重复条目。我需要增量只运行mac地址的唯一条目。

4 个答案:

答案 0 :(得分:1)

这是否符合您的要求:

@echo off
for /f %%a in ('type "file.csv"^|findstr "^10," ^|findstr ",172.20.55 ,172.20.56"^|find /c /v ""') do set AAA-NewPoolA=%%a
for /f %%a in ('type "file.csv"^|findstr "^10," ^|findstr ",172.30.55 ,172.30.56"^|find /c /v ""') do set AAA-NewPoolB=%%a
for /f %%a in ('type "file.csv"^|findstr "^11," ^|findstr ",172.20.55 ,172.20.56"^|find /c /v ""') do set AAA-ReNewPoolA=%%a
for /f %%a in ('type "file.csv"^|findstr "^11," ^|findstr ",172.30.55 ,172.30.56"^|find /c /v ""') do set AAA-ReNewPoolB=%%a
set aaa
pause

答案 1 :(得分:1)

通过复杂测试选择结果时,最简单,最快速的方法是分别识别每个结果,但累积所有相关结果组并在结束时提取所需结果。在您的情况下,这可以通过二维 array以这种方式轻松实现:

@echo off
setlocal EnableDelayedExpansion

rem Accumulate results for all ID.IP (first 3 groups) combinations
for /F "skip=1 tokens=1,5-7 delims=,." %%a in (log.log) do (
   set /A requests[%%a.%%b.%%c.%%d]+=1
)

rem Get desired results
set /A NewPoolA = requests[10.172.20.55] + requests[10.172.20.56]
set /A NewPoolB = requests[10.172.30.55] + requests[10.172.30.56]

set /A RenewPoolA = requests[11.172.20.55] + requests[11.172.20.56]
set /A RenewPoolB = requests[11.172.30.55] + requests[11.172.30.56]

echo Total new request in Pool A is %NewPoolA%
echo Total renewal request in Pool A is %RenewPoolA%

echo Total new request in Pool B is %NewPoolB%
echo Total renewal request in Pool B is %RenewPoolB%

您还可以充分利用数组提供的灵活性,以更简单的方式定义80个池。例如:

@echo off
setlocal EnableDelayedExpansion

rem Accumulate results for all ID.IP (first 3 groups) combinations
for /F "skip=1 tokens=1,5-7 delims=,." %%a in (log.log) do (
   set /A requests[%%a.%%b.%%c.%%d]+=1
)

rem Get and show desired results from a long pool definition list
for %%A in ("NewPoolA=10 172.20.55+10 172.20.56"
            "NewPoolB=10 172.30.55+10 172.30.56"
            "RenewPoolA=11 172.20.55+11 172.20.56"
            "RenewPoolB=11 172.30.55+11 172.30.56") do (
   for /F "tokens=1-5 delims==+ " %%a in (%%A) do (
      set /A %%a=requests[%%b.%%c]+requests[%%d.%%e]
      echo Total %%a request is !%%a!
   )
)

您的数据的输出示例:

C:\> test
Total NewPoolA request is 2
Total NewPoolB request is 2
Total RenewPoolA request is 0
Total RenewPoolB request is 1

您甚至可以使用第二个数组中的“池A中的新请求”替换这些结果中的“NewPoolA”消息! ;-)

最后编辑

此解决方案已多次修改,原因是新问题未包含在原始问题中。为了避免混淆,我删除了以前的解决方案并发布了最后的解决方案。下面的批处理代码仅累加对唯一MAC地址的请求,忽略等于-1的MAC地址,并允许除IP地址之外的任何字段中的点。

@echo off
setlocal EnableDelayedExpansion

rem Accumulate results for all ID.IP(first 3 groups).MAC_addr combinations
rem NEW: Ignore MAC_addresses equal to -1
for /F "skip=1 tokens=1,5,7 delims=," %%a in (log.log) do (
   if "%%c" neq "-1" for /F "tokens=1-3 delims=." %%i in ("%%b") do (
      set /A requests[%%a.%%i.%%j.%%k.%%c]+=1
   )
)

rem Get and show desired results from a long definition list
rem NEW: Only accumulate requests for unique MAC addresses (count=1)
for %%A in ("NewPoolA=10 172.20.55+10 172.20.56"
            "NewPoolB=10 172.30.55+10 172.30.56"
            "RenewPoolA=11 172.20.55+11 172.20.56"
            "RenewPoolB=11 172.30.55+11 172.30.56") do (
   for /F "tokens=1-5 delims==+ " %%a in (%%A) do (
      set %%a=0
      for /F "tokens=2 delims==" %%x in ('set requests[%%b.%%c 2^>NUL') do (
         if %%x equ 1 set /A %%a+=1
      )
      for /F "tokens=2 delims==" %%x in ('set requests[%%d.%%e 2^>NUL') do (
         if %%x equ 1 set /A %%a+=1
      )
      echo Total %%a request is !%%a!
   )
)

答案 2 :(得分:0)

你走了。我相信你可以解决剩下的问题

@echo off
setlocal

set "NewPoolA=0"
set "NewPoolB=0"
set "RenewPoolA=0"
set "RenewPoolB=0"

for /F "tokens=1-6 delims=," %%a in (log.log) do (
  if "%%~a" equ "10" (
    for /f %%b in ('echo "%%e"^|Findstr /c:"172.20.55" /c:"172.20.56"') do (
      set /a NewPoolA+=1    
    )
  )
)
echo Total new request in Pool A is %NewPoolA%

答案 3 :(得分:0)

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: remove variables starting $ or #
For %%b IN ($ #) DO FOR  /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
FOR /f "tokens=1-4delims=. " %%a IN (q21935716.txt) DO (
 IF "%%d"=="" (SET $%%a=%%b) ELSE (SET #%%b.%%c.%%d=%%a)
)

FOR /f "tokens=1,5,6,7delims=.," %%a IN (q21935716.log) DO (
 IF DEFINED $%%a IF DEFINED #%%b.%%c.%%d (SET /a !$%%a!!#%%b.%%c.%%d!+=1)
)

FOR /f "tokens=2delims==" %%a IN ('set $') DO SET %%a

GOTO :EOF

这是一个相当灵活的例程,因为你有80个游泳池。

文件q21935716.txt包含以下内容:

10 newpool
11 renewpool
A 172.20.55
A 172.20.56
B 172.30.55
B 172.30.56

显然,ID + poolname或poolsection + IP的行。

第一步是清除以$#开头的eny变量。

下一步是使用q21935716.txt.作为分隔符来阅读文件space。这意味着poolname行将有2个令牌和ip行4.然后设置变量$ poolname和#ip,分别包含ID和poolsection。

然后是读取日志文件,. ,space的分隔符,这意味着令牌1,5,6,7是有意义的。只有$ ID和#IP都存在才是感兴趣的行。在tose行中,您需要增加poolnamepoolsection。

最终for只列出了池名。