Reputation: 151
Bit of a logical maths noob question...
I am parsing log files for ip addresses and usernames.
I use this to avoid writing duplicate entries:
If Duplicate(strIP) = False Then LOG strIP & vbTab & strUser
If Duplicate(strUser) = False Then LOG strIP & vbTab & strUser
At the moment, I can avoid logging duplicates by calling this function:
Function Duplicate(strArg)
Duplicate = Flase
Set ReadLogFile = objFSO.OpenTextFile(strLogFile,1,False)
If Instr(ReadLogFile.ReadAll,strArg) Then
Duplicate = True
End If
ReadLogFile.Close
End Function
This reads the file that I am writing to as I go.
My question is: Would it be possible to check if there are duplicates, on the fly, by holding the previous value in memory instead of searching for the string in a file? The logs that I am parsing are already sorted in order.
For example, something like this:
strIP = HOLDstrIP
strUser = HOLDstrUser
If strIP <> HOLDstrIP Then
'the current string <> the previous (hold) string, so log it.
Else
'the values are the same. Increment a counter by 1
End If
And at the end of it all I would like a grand total of the number of duplicate ip addresses and the number of duplicate user names.
I hope that's not too vague and I'm sure someone has done this before!
Thanks guys.
Upvotes: 1
Views: 571
Reputation: 151
Well, I have completed the task needed by using Dictionaries!
@Ekkehard.Horner, without your help I would still be struggling with this.
Here is the relevant code I used to get the result I needed:
For myParsing In myLog
strIP = 'The parsed IP
strUser = 'The parsed user
If Not IsEmpty(HOLDstrIP) And strIP <> HOLDstrIP Then CountThemOut
objDict(strIP) = objDict(strIP) + 1
objDict(strUser) = objDict(strUser) + 1
HOLDstrIP = strIP
Next
Sub CountThemOut
Dim item
For Each item In objDict.Keys()
If objDict.Exists(item) Then LOG item & vbTab & objDict(item)
Next
HOLDstrIP = ""
objDict.RemoveAll
objDict(strIP) = 0
objDict(strUser) = 0
End Sub
'After the For loop is finished, I flush it out one last time by calling:
CountThemOut
Thank you for your help @Ekkehard.Horner!! Very much appreciated.
The log file I an writing to looks something like this:
xxx.xxx.xxx.xxx 25
username1 12
username2 15
username3 7
yyy.yyy.yyy.yyy 18
username1 10
username2 14
username3 20
:-)
Upvotes: 0
Reputation: 38755
Use a Dictionary:
Option Explicit
Dim dicSeen : Set dicSeen = CreateObject("Scripting.Dictionary")
Dim aFakeLog : aFakeLog = Split("f f a b a c d e f a b")
Dim sToken
WScript.Echo Join(aFakeLog)
WScript.Echo "--------------"
For Each sToken In aFakeLog
If Not dicSeen.Exists(sToken) Then
WScript.Echo sToken, "seen for the first time"
End If
dicSeen(sToken) = dicSeen(sToken) + 1
Next
WScript.Echo "--------------"
Dim sType
For Each sType In dicSeen.Keys()
WScript.Echo sType, dicSeen(sType)
Next
output:
cscript 21272514.vbs
f f a b a c d e f a b
--------------
f seen for the first time
a seen for the first time
b seen for the first time
c seen for the first time
d seen for the first time
e seen for the first time
--------------
f 3
a 3
b 2
c 1
d 1
e 1
Update wrt comment:
Using a function:
Option Explicit
Function firstTimeSeen(dicX, sVal)
firstTimeSeen = Not dicX.Exists(sVal)
dicX(sVal) = dicX(sVal) + 1
End Function
Dim dicSeen : Set dicSeen = CreateObject("Scripting.Dictionary")
Dim aFakeLog : aFakeLog = Split("f f a b a c d e f a b")
Dim sToken
WScript.Echo Join(aFakeLog)
WScript.Echo "--------------"
For Each sToken In aFakeLog
If firstTimeSeen(dicSeen, sToken) Then
WScript.Echo sToken, "seen for the first time"
End If
Next
WScript.Echo "--------------"
Dim sType
For Each sType In dicSeen.Keys()
WScript.Echo sType, dicSeen(sType)
Next
Upvotes: 1