Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I search for a word in a text file and then, after I find it, echo back that word and any remaining text in the text file?

-- KA

SpacerHey, Scripting Guy! AnswerScript Center

Hey, KA. Before we begin we’d like to thank the hundreds and hundreds of people who have sent Scripting Guy Jean Ross get well wishes after her unfortunate mishap at Microsoft Management Summit 2007. Not that we’ve actually received any get well wishes, mind you. But we have no doubt that they are all on the way. Consider this a thank you in advance.

Incidentally, and while we’re on the subject, there is a rumor going around that Jean slipped in her hotel room, fell, and cracked her head open. That is definitely not what happened. Instead, Jean arrived at the conference at the very moment the San Diego Convention Center was surrounded by hundreds of ninja warriors, all clad entirely in black except for a small penguin logo just above the heart. While her fellow Microsoft employees cowered in fear, begging for their lives, Jean – oblivious to the danger and willing to sacrifice everything for the good of both Microsoft and all of humanity – leaped into the fray, single-handedly defeating the entire army.

Not that she emerged unscathed, mind you; in fact, at one point a ninja shot a flaming arrow that lodged itself deep into Jean’s skull. Of course, one flaming arrow in the skull isn’t going to stop Scripting Hero Jean Ross. Instead, she simply yanked the arrow from her head and continued the battle. It was only many hours later, after she knew that everyone was safe and that the Summit had been saved, that she consented to go to the emergency room and receive first aid. That’s what really happened to Scripting Guy Jean Ross.

Or so she says, anyway.

So why would a band of ninja warriors attack the Microsoft Management Summit? To be honest, we don’t know. However, we suspect they wanted to shut down the conference before Microsoft could make the week’s most important announcement: the fact that, using a script, it’s possible to locate a specific word in a text file and then echo back just that word and any subsequent text in the file. In fact, you can do so using this script:

Const ForReading = 1

Set obJFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

strContents = objFile.ReadAll
objFile.Close

arrWords = Split(strContents, " ")
intStart = 0

For Each strWord in arrWords
    If InStr(strWord, "telescope") Then
        intStart = intStart + 1
    End If

    If intStart > 0 Then
        strFinalText = strFinalText & strWord & " "
    End If
Next
    
Wscript.Echo strFinalText

Yes, you can see why the ninjas wouldn’t want word of this to leak out, can’t you? And don’t worry: the Scripting Guys are not afraid to explain how this script works, either. However, before we do that we should note that, for this particular example, we’re assuming that we have a text file that just happens to consist of a quotation from Alice in Wonderland:

Curiouser and curiouser!' cried Alice (she was so much surprised, that 
for the moment she quite forgot how to speak good English); 'now I'm 
opening out like the largest telescope that ever was! Good-bye, feet!' 
(for when she looked down at her feet, they seemed to be almost out of 
sight, they were getting so far off).

Our task is to locate the word telescope in this file and, if and when we find the word, echo back the target word telescope and any subsequent text in the file. In other words, our script should echo back the following:

telescope that ever was! Good-bye, feet!' 
(for when she looked down at her feet, they seemed to be almost out of 
sight, they were getting so far off).

And guess what: that’s exactly what our script does do! Now all we have to do is try and figure out how it does that.

To begin with, we define a constant named ForReading and set the value to 1; we’ll use that constant when we go to open our text file. Speaking of which, we next use the following two lines of code to create an instance of the Scripting.FileSystem object and to open the file C:\Scripts\Test.txt:

Set obJFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

As soon as the file is open we use the ReadAll method to read the entire contents into a variable named strContents, and then just as quickly close the file. (Why? Because, with the contents safely tucked away in the variable strContents we no longer need the actual file itself.)

OK; now what do we do? Well, using a trick we employed during the 2007 Winter Scripting Games, we next use the VBScript Split function to split the value of strContents on the blank space:

arrWords = Split(strContents, " ")

What does that give us? That gives us an array (arrWords) consisting of all the individual words (plus any punctuation marks) in the text file, an array that starts out like this:

Curiouser 
and 
curiouser!' 
cried

Etc., etc.

Once we have the array we then set the value of a counter variable named intStart to 0:

intStart = 0

You’re right: at this point in time this doesn’t make much sense, does it? But don’t fret; everything should become crystal-clear in just a moment. After assigning a value to intStart we next set up a For Each loop to loop through all the items (words) in the array arrWords. What’s the first thing we do inside the loop? The first thing we do inside that loop is check to see if the value of the current array item contains the string telescope:

If InStr(strWord, "telescope") Then

Let’s pretend that the very first word in our text file really is the target word telescope. What do we do then? Well, all we do is increment the value of intStart by 1:

intStart = intStart + 1

Why do we do that? To answer that question, take a look at the next block of code:

If intStart > 0 Then
    strFinalText = strFinalText & strWord & " "
End If

As you can see, if intStart is greater than 0 we’re going to assign a value to a variable named strFinalText. That value is going to consist of the current value of strFinalText plus the current array item (strWord) plus a blank space. (Why a blank space? Because that enables us to restore all the blank spaces that disappeared when we called the Split method.)

See what we’re doing here? The first word in our text (and thus the first item in the array arrWords) is the word Curiouser. Does the word Curiouser contain the string telescope? No, it doesn’t; therefore the value of intStart remains 0. In turn, that means we won’t assign a new value to strFinalText; after all, we do that only if intStart is greater than 0. What about the second word in the file: and? Nope, no match there either. And so, once again, we loop around and try the next word.

Of coruse, sooner or later we will hit the word telescope; at that point we’ll change the value of intStart to 1 and assign a new value to strFinalText. And guess what? From that moment on intStart will always be greater than 1. In turn, that means that all the remaining words in the file will be assigned to strFinalText; that’s how we manage to capture both the target word and any subsequent text in the file. When we’ve finished looping through the array we finish the script by reporting back the value of strFinalText, a value that should look just like this:

telescope that ever was! Good-bye, feet!' 
(for when she looked down at her feet, they seemed to be almost out of 
sight, they were getting so far off).

And that, ninja warriors or no ninja warriors, is the answer the world has been waiting for. Whew!

Now we know what you’re thinking. And, in all fairness, at first the other Scripting Guys were a little skeptical of this whole ninja thing, too. But then we realized something: Jean has been on the team for a little over 2 years now, and during that time none of the Scripting Guys has ever been attacked by ninja warriors, not even once!

Man, she is good, isn’t she?