VBScript - Check if argument passed to Function or Sub was the same as the previous argument passed

StackOverflow https://stackoverflow.com/questions/21272514

Pergunta

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.

Foi útil?

Solução

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

Outras dicas

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

:-)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top