This month's column is going to look at how you can use string formatting functions and regular expressions to...
search for substrings within an existing string.
My previous column explained how use scripting to create an inventory of mapped drives to find duplicates. This inventory can also help users keep track of which drive letter maps to which UNC path.
The result? A file you can print out to see which user on which computer gets which file-path matches.
The raw list itself is useful, but a bit of filtering would be nice. As one reader asked in an email, "How do I make this script return only results from a particular server?"
That's not quite as simple as it sounds. It's easy to determine whether all of the contents of a variable or index in an array do match user input, but not so easy to determine whether part of that variable matches.
To do so, you'd need to know exactly where in the string the match should begin, and the count from left or right (using the Left and Right functions) to identify the match. In this particular case, we know this: The server name is always the leftmost value of oDrives.Item(i). But since we can't always make that prediction, it's good to have an alternative that doesn't demand we have that specialized knowledge.
It's possible to make the search without that specialized knowledge. However, doing so requires the use of regular expressions. Regular expressions were borrowed from Unix to enable searching strings for sub-strings. Regular expressions aren't the simplest construct to learn, but they represent the only way you can reliably search for partial string matches when the length of the string is not predictable.
Review of Left and Len
Because we know the way this input is formatted, we can cheat a little with the Len and Left string functions. Len counts the number of characters in a string. Left returns the specified number of characters in a string, counting from the left.
Review of regular expressions
Regular expressions are represented by the RegExp object, which has three properties and three methods.
The three properties are Pattern, Global and IgnoreCase. The Pattern property defines the substring you're looking for. The Global property determines whether all instances should be found (True) or just the first (False). The IgnoreCase property does pretty much what you'd expect, determining whether the pattern-matching should be case-sensitive.
The three methods are Test, Execute and Replace. The Test method checks to see whether there is a match to the string in the Pattern property. the Execute method is similar to Test, except it tells you not only if a match exists but how many matches exist and where they exist in the search. The Replace method replaces the text in the search string with new text. For example, you could use Replace to programmatically edit a Web page's source so that all instances of black became white.
Pattern matching is performed using a complex set of formatting settings which can be found at the Microsoft library.
Our goal here is to allow the person running the script to return only matches for shares from a certain computer. To make this work, we'll need to make the script accept input at runtime. We'll also have to make it so that it returns only the matches that contain a pattern matching the user's input. We'd also like to tell the user if the computer on which they're running inventory has no drives mapped to the server name provided as input, just so the person running the script knows that the script worked as expected—it just returned no results.
My February 2006 column discussed how to store user input and provided guidance on getting the input we need. Since our goal here is simple—we just want to know the name of the server a share is available from—we don't need to write a complete help file. (If you want to create a help file, see the column entitled Enhancing scripts that require user input.) Rather, we want to tell the user to provide the name of a server, if they haven't already, or tell them how to get a listing of all mapped drives.
To make this work, you must insert the sort order at the right moment: after the script has the information but before it's told to the user.
You can sort the input inflexibly (using the Len and Left string functions) or via the more flexible but more complicated method of Regular Expressions. To sort the input using string functions, use Len to count the number of characters in the server name the user supplied as an argument. Having done that, save the result to a variable. Supply that variable to Left like this: Left(variable+2) to add the forward slashes preceding the server name, and apply the string function to the user input. If the input matches the leftmost part of the string, then you can return that output to the user.
To sort the input using Regular Expressions, first create a regular expression object, then search for the server name provided. In this case, you should be able to ignore the backslashes, since you don't need to count. Instead, use the ^ character and $ character to show the beginning and end of input.
Want to allow the user to submit two server names to search for? The script will store the input as separate arguments: Wscript.Arguments(0) and Wscript.Arguments(1). Assuming you store these inputs as sServer01 and sServer02 for easier handling, you can format the pattern using the | divider, like this: ^sServer01$ | ^sServer02$.
You can read all of Christa Anderson's scripting columns on SearchWinComputing.com
|ABOUT THE AUTHOR:|
| Christa Anderson
A Terminal Services MVP, Christa Anderson is the strategic technology manager for visionapp She formerly was program manager for the Microsoft Terminal Services team. She is an internationally known authority on scripting, the author of Windows Terminal Services, The Definitive Guide to MetaFrame XP, and co-author of the book Mastering Windows 2003 Server. If you have a scripting question for Christa, please e-mail her at editor@SearchWincomputing.com. She often uses these emails as fodder for her scripting columns.