我有兴趣学习如何提取信息
来自文本日志文件(log.txt
),通过脚本( Linux bash 或 Windows批处理或 Python )。所有这些信息都应写在另一个文本文件(results.txt
)中或打印在终端上。
基本上,所有其他日志条目(即blah blah
都被忽略)。
例如,对于以下文本日志文件,其中每行以时间戳开头,后跟空格,虚线( - )和一个或多个空格,后跟关键字:
11:59:35.875 - 行动 - 写作(34)开始
11:59:35.875 - 等等等等
11:59:35.875 - 等等等等
11:59:35.877 - 等等等等
11:59:35.897 - KEYWORD_1
11:59:35.975 - 行动 - 写作(34)结束
11:59:36.992 - KEYWORD_1
11:59:36.999 - KEYWORD_1
11:59:37.535 - 等等等等
11:59:37.545 - ACTION_A - STATE:type 2
11:59:37.575 - 等等等等
11:59:37.577 - 等等等等
11:59:37.845 - KEYWORD_2
11:59:37.945 - ACTION_B结果
11:59:37.950 - 等等等等
11:59:38.075 - action - WRITE(22)start
11:59:38.075 - 等等等等
11:59:38.085 - blah blah
11:59:38.097 - KEYWORD_2
11:59:39.975 - 行动 - 写作(22)结束
首先,我想计算每个KEYWORD_1
和KEYWORD_2
的出现次数(例如分别为2和2)。
其次,我希望能够打印每个KEYWORD
次出现的时间戳,例如第一次出现11:59:35.897
时会KEYWORD_1
。
最后,找到两个日志条目之间经过的时间:
- action - WRITE(#) start
开头并以- action - WRITE(#) end
结尾的人,其中#
是任意整数,例如11:59:35.975 - 11:59:35.875 = 1ms
第一个WRITE(34)
- ACTION_A ...
开头且以ACTION_B ...
结尾的人,例如11:59:37.545 - 11:59:37.945 = 4ms
为第一个ACTION_A .. ACTION_B
。我已尝试find /c "KEYWORD_1" log.txt >results.txt
(Windows批处理)来计算出现次数,但我无法提取相应的时间戳。对于其他要求,我不知道如何开始,因为我以前没有这种行为的经验。尝试根据我的需要调整此question的答案,但没有成功。
非常感谢任何代码片段示例或与相关资源的链接。
答案 0 :(得分:1)
嗯,因为看起来这不是一项艰巨的任务,我把它作为挑战。
我使用内部for /f
和findstr.exe
进行解析。 (完成:子:Procline需要更多的时间计算工作。)
Keywords.txt:
action
KEYWORD_1
ACTION_A
KEYWORD_2
ACTION_B
批处理文件
@echo off & setlocal EnableExtensions EnableDelayedExpansion
Set Log=LogFile.txt
Set Key=Keywords.txt
For /f "tokens=1-5* delims=-() " %%A in (
'findstr /i /G:%Key% %Log% ^|Sort /+16'
) Do call :ProcLine "%%A" %%B %%C %%D %%E
Echo Count
set _
Pause
Goto :Eof
:ProcLine
Set /A _%2+=1
Echo %~1 - %2 %3 %4 %5
:: Do we need to calc times?
Echo %5 | findstr /i "end start" >Nul 2>&1 || Goto :Eof
Call :CalcMsecs %1 x%5
If /i %5 neq start Goto :Eof
Set /a xElap=xend-xstart
If %xElap% gtr 0 Echo Elapsed Time: %xElap% msec
Goto :Eof
:CalcMsecs
Setlocal&Set T=%~1
Set /A _h=%T:~0,2%,_m=%T:~3,2%,_s=%T:~6,2%,_ms=%T:~9,3%
Set /A _m+=_h*60
Set /A _s+=_m*60
Set /A _ms+=_s*1000
:: set _
Endlocal&Set %2=%_ms%&Goto :Eof
输出(到现在为止,仍在提炼)
11:59:39.975 - action WRITE 22 end
11:59:38.075 - action WRITE 22 start
Elapsed Time: 1914 msec
11:59:35.975 - action WRITE 34 end
11:59:35.875 - action WRITE 34 start
Elapsed Time: 100 msec
11:59:37.545 - ACTION_A STATE: type 2
11:59:37.945 - ACTION_B result
11:59:36.992 - KEYWORD_1
11:59:35.897 - KEYWORD_1
11:59:36.999 - KEYWORD_1
11:59:38.097 - KEYWORD_2
11:59:37.845 - KEYWORD_2
Count
_action=6
_ACTION_A=1
_ACTION_B=1
_KEYWORD_1=3
_KEYWORD_2=2
有一个14毫秒无处可来的缺陷,但对我来说已经太晚了
答案 1 :(得分:1)
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q40441783.txt"
:: occurrence count for KEYWORD_1,KEYWORD_2,KEYWORD_3
FOR %%k IN (KEYWORD_1 KEYWORD_2 KEYWORD_3) DO (
FOR /f "delims=" %%c IN ('type "%filename1%"^|FIND /c "%%k"') DO ECHO %%k : %%c times
)
:: Timestamp display for KEYWORD_1,KEYWORD_2,KEYWORD_3
FOR %%k IN (KEYWORD_1 KEYWORD_2 KEYWORD_3) DO (
type "%filename1%"|FIND "%%k"
)
:: remove variables starting $ or #
For %%b IN ($ #) DO FOR /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
:: action - WRITE(#)
FOR /f "usebackqtokens=1*delims=- " %%a IN ("%filename1%") DO (
REM interested in "pattern - WRITE(#) start/end"
FOR /f "tokens=1-3*delims=-()" %%A IN ("%%b") DO (
REM %%A is action, %%B "WRITE" %%C # %%D " start"/" end"
IF "%%B"==" WRITE" IF "%%D"==" start" SET "$%%C %%A$=%%a"
IF "%%B"==" WRITE" IF "%%D"==" end" SET "#%%C %%A#=%%a"
CALL :formatch&CALL :report "WRITE(%%C)"
)
)
SET $ 2>nul
SET # 2>nul
:: remove variables starting $ or #
For %%b IN ($ #) DO FOR /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
FOR /f "usebackqtokens=1*delims=- " %%a IN ("%filename1%") DO (
REM interested in "ACTION_A/ACTION_B elapsed time"
FOR /f "tokens=1*delims=- " %%A IN ("%%b") DO (
REM %%A is action, %%B remainder of line
IF "%%A"=="ACTION_A" SET "$1$=%%a"&SET "_actiona=%%B"
IF "%%A"=="ACTION_B" SET "#1#=%%a"
CALL :formatch
CALL :report "%%_actiona%% %%B"
)
)
SET $ 2>nul
SET # 2>nul
GOTO :EOF
:: See whether a $something$ AND a #something# exist and report if so
:formatch
SET "elapsed="
FOR /f "tokens=1,2delims=$=" %%m IN ('set $ 2^>nul') DO (
IF DEFINED #%%m# (
CALL :elapsed %%n %%#%%m#%%
SET "#%%m#="
SET "$%%m$="
)
)
GOTO :eof
:report
IF DEFINED elapsed ECHO %elapsed% %~1
GOTO :eof
:: get %2 - %1 both in HH:mm.ss.ttt format
:elapsed
FOR /f "tokens=1-4delims=:." %%w IN ("%2") DO (SET /a hh=2%%w&SET /a mm=2%%x&SET /a ss=2%%y&SET /a ttt=2%%z)
FOR /f "tokens=1-4delims=:." %%w IN ("%1") DO (SET /a hh-=1%%w&SET /a mm-=1%%x&SET /a ss-=1%%y&SET /a ttt-=1%%z)
:: compensate for "negatives"
IF %ttt% lss 1000 set/a ttt+=1000&set/a ss-=1
IF %ss% lss 100 set/a ss+=60&set/a mm-=1
IF %mm% lss 100 set/a mm+=60&set/a hh-=1
IF %hh% lss 100 set/a hh+=24
SET "elapsed=%hh:~-2%:%mm:~-2%:%ss:~-2%.%ttt:~-3%"
GOTO :eof
GOTO :eof
您需要更改sourcedir
的设置以适合您的具体情况
我使用了一个名为q40441783.txt
的文件,其中包含我的测试数据。
有趣的运动。
前两个步骤相当明显。我添加了KEYWORD_3
以确保为"未找到"生成了正确的报告。请注意,您为KEYWORD_1声明了2次出现。实际上,在您发布的数据中有3个。
下一步需要一些解释。我要做的第一件事是确保没有变量从#
或$
开始。
接下来 - 分析每一行,首先在第一个-
或空间上进行分割,然后在-()
上的第一个分隔符序列标记之外处理该部分,以便使用该标记如REM
声明中所述。然后,我们将变量$...$
或#...#
设置为%%a
中的时间。 ...
这是日志条目的唯一部分 - 数字和操作。然后检查同一$...$
是否同时存在#...#
和...
,如果是,请清除$#...$#
个变量,计算已用时间,重建行和报告。
经过时间的计算在每个变量的开头之前加上2,以确保它们不会启动0
并可能被视为八进制。然后通过减去开始时间来拉动相同的技巧,使用前置1来产生应该是3位数的结果(4表示ms)。如果检测到的数字较少,那么我们需要添加一个合适的数字,并从下一个更高的时间元素中扣除一个。
action_a / _b时序的处理基本相同,但是在$!$ /#1#中记录开始/结束时间,因为没有迹象表明字符串的性质action_a
和{{ 1}}我们被迫假设适当的事件不会重叠。
答案 2 :(得分:1)
这是python选项:
from datetime import datetime, timedelta
keywords = ['KEYWORD_1', 'KEYWORD_2']
actions = ['WRITE(']
kws_dict = {}
acts_dict = {}
with open('sample.log') as l:
with open('filtered.log', 'w') as f:
for line in l:
if any(k in line for k in keywords) and len(line) > 1:
entry = line.split('-')[1].strip()
dt = line.split('-')[0].strip()
if entry in kws_dict:
kws_dict[entry].append(datetime.strptime(dt, '%H:%M:%S.%f'))
else:
kws_dict[entry] = [datetime.strptime(dt,'%H:%M:%S.%f')]
elif any(a in line for a in actions) and len(line) > 1:
dt = line.split('-')[0].strip()
action = line.split(' ')[-2].strip()
action_type = line.split(' ')[-1].strip()
if action in acts_dict.keys():
acts_dict[action][action_type] = datetime.strptime(dt,'%H:%M:%S.%f')
else:
acts_dict[action] = {action_type:datetime.strptime(dt,'%H:%M:%S.%f')}
# print results
for k in kws_dict.keys():
print('%s occured %s times' % (k, len(kws_dict[k])))
# comment below if you don't need specific timestamps
for i in kws_dict[k]:
print('\t%s' % i.strftime('%H:%M:%S.%f'))
#iterate over actions, then action_types (start, end)
for a, at in acts_dict.iteritems():
print('%s: Elapsed time %s' % (a, at['end'] - at['start']))
# for at, t in acts_dict[a].iteritems():
# print('\t%s: %s' % (at, t.strftime('%H:%M:%S.%f')))
## Raw data in case you need it
#print("Actions:\n", acts_dict)
产生:
KEYWORD_1发生了3次 11:59:35.897000
11:59:36.992000
11:59:36.999000
KEYWORD_2发生了2次 11:59:37.845000
11:59:38.097000
写(34):经过时间0:00:00.100000
写(22):经过时间0:00:01.900000
答案 3 :(得分:0)
我不知道这会有多好,但为什么不尝试阅读每一行,如果关键字在其中,请将其写在另一个文件上。 您可以尝试执行以下操作:
with open('log.txt','r') as f:
for line in f:
if 'KEYWORD' in line:
with open('results.txt','a') as z:
z.write(line)