Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

File parsing on steroids needed

1 view
Skip to first unread message

Highlander

unread,
Feb 28, 2006, 9:56:30 AM2/28/06
to
I've got a number of SQL script output log files I have to review.

An error free log looks like this:
~~~~~~~ start of file ~~~~~~~
1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11> 1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11>
12> 13> 14> 15> 16> 17> 18> 19> 20> 21> 22> 23> 24> 25> 26> 27> 28> 29>
30> 31> 32> 33> 34> 35> 36> 37> 38> 39> 40> 41> 42> 43> 44> 45> 46> 47>
48> 49> 50> 51> 52> 53> 54> 55> 56> 57> 58> 59> 60> 61> 62> 63> 64> 65>
66> 67> 68> 1> 2> 3> 4> 5> 6> 7> 8> 9>
~~~~~~ end of file ~~~~~~~~~

A log that has errors looks like this:
~~~~~~~ start of file ~~~~~~~
1> 2> 3> 1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11> 12> 1> 2> 3> 4> 5> 6> 7> 8>
9> 10> 11> 12> 13> 14> 15> 16> 17> 18> 47> 48> 49> 50> 51> 52> 53> 54>
55> 56> 57> 58> 59> Msg 262, Level 14, State 1, Server
DB019-APP0553-S, Procedure BUP_SAVE_POPULAR_SEARCH, Line 65535
CREATE PROCEDURE permission denied in database 'Metrics'.
1> 2> 3> 4> 5> 6> 7> 8> 9> Msg 208, Level 16, State 11, Server
DB019-APP0553-S, Line 2
Invalid object name 'WebAdmin.BUP_SAVE_POPULAR_SEARCH'. 1> 2> 3> 4> 1>
2> 1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11> 1> 2> 3> 4> 5> 6> 7> 8> 9> 10>
11> 12> 13> 14>
~~~~~~ end of file ~~~~~~~~~

An error in the log is defined by any character that's not a number, or
a greater than (>) symbol. I need a script to search the file and
report if the log is error free, or not. Any help would be greatly
appreciated. Thanks!

Lloyd Gilbert

unread,
Feb 28, 2006, 10:48:41 AM2/28/06
to


This is a bit horrible: A function that takes a string as its
parameter (the ReadAll() of your log file), and then removes all
numbers, ">" signs and spaces, and then returns true or false
depending on whether the resulting string is of zero length.

It might be of some use to you.
Lloyd

function CheckForErrors(s)
dim str
dim ret

str = s
str = replace(str, "1", "")
str = replace(str, "2", "")
str = replace(str, "3", "")
str = replace(str, "4", "")
str = replace(str, "5", "")
str = replace(str, "6", "")
str = replace(str, "7", "")
str = replace(str, "8", "")
str = replace(str, "9", "")
str = replace(str, "0", "")
str = replace(str, ">", "")
str = replace(str, " ", "")

if len(str)>0 then
ret = false
else
ret = true
end if

CheckForErrors = ret
end function


Georges

unread,
Feb 28, 2006, 10:54:35 AM2/28/06
to
Hello,
Maybe by using regular expressions like this

Dim fso, f
Dim regEx, Match, Matches

Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("c:\temp\testfile.txt",1)
ReadAllTextFile = f.ReadAll

Set regEx = New RegExp
regEx.Pattern = "[^0-9> \n\r\s]"
regEx.Global = True
Set Matches = regEx.Execute(ReadAllTextFile)

For Each Match in Matches
RetStr = RetStr & "Found at position " & Match.FirstIndex & ". Value :
" & Match.Value & vbCRLF
Next

if RetStr <>"" then
MsgBox("Errors in log")
MsgBox(RetStr)
else
MsgBox("No error in log")
end if

Regards
Georges

"Highlander" <tron...@msn.com> a écrit dans le message de news:
1141138590....@u72g2000cwu.googlegroups.com...

Richard Mueller

unread,
Feb 28, 2006, 1:19:47 PM2/28/06
to
Hi,

If all errors begin with "Msg" you could use InStr to seach for that string.
If InStr returns 0, there are no errors.

--
Richard
Microsoft MVP Scripting and ADSI
Hilltop Lab - http://www.rlmueller.net

"Highlander" <tron...@msn.com> wrote in message
news:1141138590....@u72g2000cwu.googlegroups.com...

Highlander

unread,
Feb 28, 2006, 3:03:49 PM2/28/06
to
Georges that works great! Thanks!

I did find that for fairly large log files, with alot of errors, the
script doesn't return anything - no error messages, no MsgBox. It's
either blowing up, or I'm not patient enough to allow it to finish. In
any case, I resolved this by changing this line:

RetStr = RetStr & "Found at position " & Match.FirstIndex & ". Value :
" & Match.Value & vbCRLF

to this:

RetStr = RetStr & Match.FirstIndex

I don't need to record the found matches anyway, I just need the
notification. A large log file will still take a bit of time to finish,
but it works exactly how I need it to.

Thanks again!

- Dave

Georges

unread,
Mar 1, 2006, 3:56:24 AM3/1/06
to
Hello Highlander,
If it's too long, you could stop at the first error by exiting the for like
this

For Each Match in Matches

' an error has been found
RetStr = "Error found"
exit for
Next

Another thing is that the file is read entirely.
You can also open it, read 1 line at the time, anlysing it and stop if an
error is found
Like this

Dim fso, f
Dim regEx, Match, Matches, RetStr

Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("c:\temp\testfile.txt",1)

Set regEx = New RegExp


regEx.Pattern = "[^0-9> \n\r\s]"
regEx.Global = True

RetStr = ""

do while not f.AtEndOfStream
line=f.ReadLine
Set Matches = regEx.Execute(line)

For Each Match in Matches

' an error has been found
RetStr = "Error found"
' exiting loop for
exit for

Next

if RetStr<>"" then
' exiting loop do
exit do
end if
loop

f.close()

if RetStr <>"" then
MsgBox("Errors in log")

else
MsgBox("No error in log")
end if

Regards
Georges

"Highlander" <tron...@msn.com> a écrit dans le message de news:

1141157029.5...@j33g2000cwa.googlegroups.com...

Highlander

unread,
Mar 6, 2006, 10:40:50 AM3/6/06
to
Thanks for the suggestion Georges, you've been a great help! Speaking
of file parsing, I have another issue that I wonder if you could help
me with.

I have a text file that looks like this:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[LEVEL]
1/25/2006 9:01:28 AM=ASDT v4.5
2/13/2006 11:02:00 AM=ASDT v4.6
2/24/2006 12:58:25 PM=ASDT v4.7
2/27/2006 2:08:48 PM=ASDT v4.8


[INSTALL]
1/25/2006 9:01:28 AM=User3 - ASDT Code Release - STR 7009
2/13/2006 11:02:00 AM=User5 - ASDT Code Release - STR 7212
2/24/2006 12:58:25 PM=User5 - ASDT Code Release - STR 7359
2/27/2006 2:08:48 PM=User2 - ASDT Code Release - STR 7375
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I'd like to be able to write to this file by making entries in both the
[LEVEL] and [INSTALL] sections - so that afterwards it looks like this:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[LEVEL]
1/25/2006 9:01:28 AM=ASDT v4.5
2/13/2006 11:02:00 AM=ASDT v4.6
2/24/2006 12:58:25 PM=ASDT v4.7
2/27/2006 2:08:48 PM=ASDT v4.8
3/6/2006 9:25:37 AM=MY NEW ENTRY IS HERE

[INSTALL]
1/25/2006 9:01:28 AM=User3 - ASDT Code Release - STR 7009
2/13/2006 11:02:00 AM=User5 - ASDT Code Release - STR 7212
2/24/2006 12:58:25 PM=User5 - ASDT Code Release - STR 7359
2/27/2006 2:08:48 PM=User2 - ASDT Code Release - STR 7375
3/6/2006 9:25:37 AM=MY NEW ENTRY IS HERE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I imagine this could be done using RegExp, InStr, or some combination
thereof. Note that the seperation between the end of the [LEVEL]
section, and the beginning of the [INSTALL] section, can vary between
no carriage returns at all, to any number (typically one or two) of
carriage returns.

Any ideas on how to do this would be greatly appreciated. Thanks!

- Dave

McKirahan

unread,
Mar 6, 2006, 11:15:56 AM3/6/06
to
"Highlander" <tron...@msn.com> wrote in message
news:1141659649.9...@e56g2000cwe.googlegroups.com...

[snip]

Will this help?


Option Explicit
'*
'* Declare Constants
'*
Const cVBS = "ini.vbs"
Const cOT1 = "ini1.txt"
Const cOT2 = "ini2.txt"
Const cIN1 = "[LEVEL]"
Const cIN2 = "[INSTALL]"
'*
Const ForReading = 1
Const ForWriting = 2
'*
'* Delare Variables
'*
Dim booIN1
booIN1 = False
Dim booIN2
booIN2 = False
Dim strNEW
strNEW = Now
strNEW = Month(strNEW) & "/" & Day(strNEW) & "/" & Year(strNEW) & "
"
strNEW = strNEW & Time "=MY NEW ENTRY IS HERE"
Dim arrOT1
Dim intOT1
Dim strOT1
Dim intOT2
Dim strOT2
'*
'* Declare Objects
'*
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objOT1
Set objOT1 = objFSO.OpenTextFile(cOT1,ForReading)
Dim objOT2
Set objOT2 = objFSO.OpenTextFile(cOT2,ForWriting,True)
'*
'* Read File, Insert new entries, Write file.
'*
strOT1 = objOT1.ReadAll()
arrOT1 = Split(strOT1,vbCrLf)
For intOT1 = 0 To UBound(arrOT1)
strOT2 = arrOT1(intOT1)
If Left(strOT2,Len(cIN1)) = cIN1 Then booIN1 = True
If Left(strOT2,Len(cIN2)) = cIN1 Then booIN2 = True
If strOT2 = "" Then
If booIN1 Then
booIN1 = False
objOT2.WriteLine(strNEW)
ElseIf booIN2 Then
booIN2 = False
objOT2.WriteLine(strNEW)
End If
End If
objOT2.WriteLine(strOT2)
Next
'*
'* Destroy Objects
'*
Set objOT1 = Nothing
Set objOT2 = Nothing
Set objFSO = Nothing
'*
'* Finished
'*
MsgBox strNEW,vbInformation,cVBS

This presumes that the last line contains CrLf.


McKirahan

unread,
Mar 6, 2006, 11:23:06 AM3/6/06
to
"McKirahan" <Ne...@McKirahan.com> wrote in message
news:YK6dnYyFy8G...@comcast.com...

[snip]

In case the last line doesn't contain CrLf,
insert this line after the "Next" statement:

If booIN2 Then objOT2.WriteLine(strNEW)


Highlander

unread,
Mar 6, 2006, 1:32:28 PM3/6/06
to

Hi McKirahan thanks for the reply. Using "ini1.txt" as my original text
file, your script created a new text file "ini2.txt", which had a new
entry in the [LEVEL] section only.

I need to update the original file, versus creating a new file. I also
need the entry text ("MY NEW ENTRY IS HERE") to be two different
variables, one for the [LEVEL] section and one for the [INSTALL]
section.

The entries for each section would look something like this:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[LEVEL]
...
...
3/6/2006 12:28:47 PM=ASDT v4.8

[INSTALL]
...
...
3/6/2006 12:28:47 PM=User6 - ASDT Code Release - STR 7421
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

McKirahan

unread,
Mar 6, 2006, 6:34:55 PM3/6/06
to
"Highlander" <tron...@msn.com> wrote in message
news:1141669948.3...@e56g2000cwe.googlegroups.com...

[snip]

> Hi McKirahan thanks for the reply. Using "ini1.txt" as my original text
> file, your script created a new text file "ini2.txt", which had a new
> entry in the [LEVEL] section only.

Did you forget to add this line:

If booIN2 Then objOT2.WriteLine(strNEW)

> I need to update the original file, versus creating a new file. I also
> need the entry text ("MY NEW ENTRY IS HERE") to be two different
> variables, one for the [LEVEL] section and one for the [INSTALL]
> section.
>
> The entries for each section would look something like this:
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> [LEVEL]
> ...
> ...
> 3/6/2006 12:28:47 PM=ASDT v4.8
>
> [INSTALL]
> ...
> ...
> 3/6/2006 12:28:47 PM=User6 - ASDT Code Release - STR 7421
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>

Try this version which overwrites the input file.

Option Explicit
'*
'* Declare Constants
'*
Const cVBS = "ini.vbs"

Const cOTF = "ini.txt"


Const cIN1 = "[LEVEL]"
Const cIN2 = "[INSTALL]"
'*
Const ForReading = 1
Const ForWriting = 2
'*
'* Delare Variables
'*
Dim booIN1
booIN1 = False
Dim booIN2
booIN2 = False

Dim arrNEW()
Dim intNEW
intNEW = 0


Dim strNEW
strNEW = Now
strNEW = Month(strNEW) & "/" & Day(strNEW) & "/" & Year(strNEW) & "
"
strNEW = strNEW & Time

strNEW = strNEW & "=MY NEW ENTRY IS HERE"
Dim arrOTF
Dim intOTF
Dim strOTF


'*
'* Declare Objects
'*
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")

Dim objOTF
'*
'* Read File
'*
Set objOTF = objFSO.OpenTextFile(cOTF,ForReading)
strOTF = objOTF.ReadAll()
arrOTF = Split(strOTF,vbCrLf)
ReDim arrNEW(UBound(arrOTF)+3)
For intOTF = 0 To UBound(arrOTF)
strOTF = arrOTF(intOTF)
If Left(strOTF,Len(cIN1)) = cIN1 Then booIN1 = True
If Left(strOTF,Len(cIN2)) = cIN1 Then booIN2 = True
If strOTF = "" Then


If booIN1 Then
booIN1 = False

intNEW = intNEW + 1
arrNEW(intNEW) = strNEW


ElseIf booIN2 Then
booIN2 = False

intNEW = intNEW + 1
arrNEW(intNEW) = strNEW
End If
End If
intNEW = intNEW + 1
arrNEW(intNEW) = strOTF
Next
If booIN2 Then
intNEW = intNEW + 1
arrNEW(intNEW) = strNEW
End If
Set objOTF = Nothing
'*
'* Write file
'*
Set objOTF = objFSO.OpenTextFile(cOTF,ForWriting,True)
For intNEW = 1 To UBound(arrNEW)
strOTF = arrNEW(intNEW)
objOTF.WriteLine(strOTF)
Next
Set objOTF = Nothing


'*
'* Destroy Objects
'*

Highlander

unread,
Mar 6, 2006, 9:48:26 PM3/6/06
to
There are two "Next" statements; I've tried inserting this line after
each:

If booIN2 Then objOT2.WriteLine(strNEW)

The result is always the same - I get a new entry in the [LEVEL]
section only. Plus, each text file I have to edit is different; some
may have a last line that contains CrLf, some may not.

I still also need two variables that will each contain different text,
one for each section [LEVEL] and [INSTALL].

I'm stumped.

McKirahan

unread,
Mar 6, 2006, 9:55:02 PM3/6/06
to
"Highlander" <tron...@msn.com> wrote in message
news:1141699706.4...@p10g2000cwp.googlegroups.com...

> There are two "Next" statements; I've tried inserting this line after
> each:
>
> If booIN2 Then objOT2.WriteLine(strNEW)
>
> The result is always the same - I get a new entry in the [LEVEL]
> section only. Plus, each text file I have to edit is different; some
> may have a last line that contains CrLf, some may not.
>
> I still also need two variables that will each contain different text,
> one for each section [LEVEL] and [INSTALL].
>
> I'm stumped.
>

My first solution only had one Next statement.

Did you try my second solution "as is"?


McKirahan

unread,
Mar 7, 2006, 7:40:12 AM3/7/06
to
"Highlander" <tron...@msn.com> wrote in message
news:1141699706.4...@p10g2000cwp.googlegroups.com...

[snip]

> I still also need two variables that will each contain different text,
> one for each section [LEVEL] and [INSTALL].

In your example the new lines (variables?) did not contain "different text";
"3/6/2006 9:25:37 AM=MY NEW ENTRY IS HERE" is repeated.

[LEVEL]
1/25/2006 9:01:28 AM=ASDT v4.5
2/13/2006 11:02:00 AM=ASDT v4.6
2/24/2006 12:58:25 PM=ASDT v4.7
2/27/2006 2:08:48 PM=ASDT v4.8
3/6/2006 9:25:37 AM=MY NEW ENTRY IS HERE

[INSTALL]


1/25/2006 9:01:28 AM=User3 - ASDT Code Release - STR 7009
2/13/2006 11:02:00 AM=User5 - ASDT Code Release - STR 7212
2/24/2006 12:58:25 PM=User5 - ASDT Code Release - STR 7359

Highlander

unread,
Mar 7, 2006, 11:55:45 AM3/7/06
to
Yeah sorry about the confusion regarding the two variables - I
definitely need different text.

I had also tried your solution as is, before inserting the line after
the Next statements - that wouldn't work either.

After searching the newsgroup and combining some code snippets, I tried
a new approach. So far it works great. I think it's a little clunky
though; it could probably be cleaned up and consolidated a bit:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Const OverwriteExisting = True


Set fso = CreateObject("Scripting.FileSystemObject")

'~~~ Remove all blank lines from current INI file
Dim INIFile, Temp1, Backup
INIFile = "ini.txt"
Temp = "Temp.txt"
Backup = "ini.backup.txt"

Set curfile = fso.OpenTextFile(INIFile)
Set newfile = fso.CreateTextFile(Temp)
Do until curfile.AtEndOfStream
line = curfile.readLine
IF len(line)>0 Then newfile.writeLine line
Loop
curfile.Close
newfile.Close

'~~~ Backup original INI file
IF fso.FileExists(Backup) Then
fso.DeleteFile(Backup)
End IF
fso.MoveFile INIFile , Backup

'~~~ Copy new (de-blanked) file to INI file
fso.CopyFile Temp, INIFile, True
fso.DeleteFile(Temp)

'~~~ Read the INI file and create arrays
'~~~ from the Level and Install sections
Dim AllText, delim, ptr, Level, Install
Set TextFile = FSO.OpenTextFile(INIFile , 1)

AllText = TextFile.ReadAll
delim = "[INSTALL]"
ptr = inStrRev(AllText,delim)
IF NOT ptr = 0 then
Level = left(AllText, ptr-1)
Install = mid(AllText, ptr)
End IF
TextFile.Close

'~~~ Append the timestamp and new text entries to each array
Dim LevelNew, InstallNew
LevelNew = Level & NOW & "=" & "New LEVEL section text here."
InstallNew = Install & NOW & "=" & "New INSTALL section text here."

'~~~ Write the completed arrays to the INI file
Set TextFile = FSO.OpenTextFile(INIFile, 2, True)
Dim ArrLevel
ArrLevel = Split(LevelNew,vbCrlf)
For i = 0 To UBound(ArrLevel)
EachLine = ArrLevel(i)
TextFile.WriteLine EachLine
Next
TextFile.WriteLine vbCrLf
TextFile.Close

Set TextFile = FSO.OpenTextFile(INIFile, 8, True)
Dim ArrInstall
ArrInstall = Split(InstallNew,vbCrlf)
For i = 0 To UBound(ArrInstall)
EachLine = ArrInstall(i)
TextFile.WriteLine EachLine
Next
TextFile.Close

Set fso = nothing
Set curfile = nothing
Set newfile = nothing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Thanks again for all your help!

Looks like I'm good to go. Any suggestions for improving the above code
would be greatly appreciated.

- Dave

McKirahan

unread,
Mar 7, 2006, 12:22:30 PM3/7/06
to
"Highlander" <tron...@msn.com> wrote in message
news:1141750544....@j52g2000cwj.googlegroups.com...

> I had also tried your solution as is, before inserting the line after
> the Next statements - that wouldn't work either.

Below is a minor update to my last solution.
It supports different text for [LEVEL] and [INSTALL].
I'm curious as to why doesn't it work for you?

Option Explicit
'*
'* Declare Constants
'*
Const cVBS = "ini.vbs"
Const cOTF = "ini.txt"
Const cIN1 = "[LEVEL]"
Const cIN2 = "[INSTALL]"

Const cLEV = "=New LEVEL section text here."
Const cINS = "=New INSTALL section text here."


'*
Const ForReading = 1
Const ForWriting = 2
'*
'* Delare Variables
'*
Dim booIN1
booIN1 = False
Dim booIN2
booIN2 = False
Dim arrNEW()
Dim intNEW
intNEW = 0
Dim strNEW
strNEW = Now

' uncomment the following if you need "m/d/yyyy" instead of "mm/dd/yyyy":
' strNEW = Month(strNEW) & "/" & Day(strNEW) & "/" & Year(strNEW) & "


"
' strNEW = strNEW & Time

Dim arrOTF
Dim intOTF
Dim strOTF
'*
'* Declare Objects
'*
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objOTF
'*
'* Read File
'*
Set objOTF = objFSO.OpenTextFile(cOTF,ForReading)
strOTF = objOTF.ReadAll()
arrOTF = Split(strOTF,vbCrLf)
ReDim arrNEW(UBound(arrOTF)+3)
For intOTF = 0 To UBound(arrOTF)
strOTF = arrOTF(intOTF)
If Left(strOTF,Len(cIN1)) = cIN1 Then booIN1 = True
If Left(strOTF,Len(cIN2)) = cIN1 Then booIN2 = True
If strOTF = "" Then
If booIN1 Then
booIN1 = False
intNEW = intNEW + 1

arrNEW(intNEW) = strNEW & cLEV


ElseIf booIN2 Then
booIN2 = False
intNEW = intNEW + 1

arrNEW(intNEW) = strNEW & cINS


End If
End If
intNEW = intNEW + 1
arrNEW(intNEW) = strOTF
Next
If booIN2 Then
intNEW = intNEW + 1

arrNEW(intNEW) = strNEW & cINS


End If
Set objOTF = Nothing
'*
'* Write file
'*
Set objOTF = objFSO.OpenTextFile(cOTF,ForWriting,True)
For intNEW = 1 To UBound(arrNEW)
strOTF = arrNEW(intNEW)
objOTF.WriteLine(strOTF)
Next
Set objOTF = Nothing
'*
'* Destroy Objects
'*
Set objFSO = Nothing
'*
'* Finished
'*
MsgBox strNEW,vbInformation,cVBS


I ensure that both entries have the same timestamp.
Using "Now" twice may give different timestamps.

Also, when I use now, it gives me "mm/dd/yyyy"
not "m/d/yyyy" as you say you want.


0 new messages