4.6. What's Next ?So far, we've made good progress and have covered all the basics of the MSH environment and its language features. In the next chapter, we'll spend some time focusing on the pipeline, examining its behavior in more depth, and looking at how we can really make use of the rich data that passes through it. |
Chapter 5. Adding to the MSH ToolkitWe covered a lot of new ground in the preceding chapters that focused on exploration in interactive mode. In the examples that follow in this chapter, we'll step back and look at some of the plumbing of MSH that makes it all possible. We'll cover some of the generic cmdlets in more detail, discuss how data can be persisted to and retrieved from a filesystem, and take a deeper look at exactly what a pipeline object is and how the .NET Framework Class Library can provide an extra dimension of functionality. |
5.1. Extend the Toolkit with Generic CmdletsThere are several cmdlets that keep coming up again and again: where-object , sort -object , select-object , format-table , and a handful of others. These cmdlets are simple in their design and offer almost limitless possibilities for reuse in all kinds of situations. There are several more processing cmdlets that we'll discuss in this section that are also generic in nature yet draw strength from their simplicity.
5.1.1. How Do I Do That?We've already covered the select-object cmdlet, so we can begin there. Previously, we saw a couple of its capabilitiesfor example, how it can create cut-down copies of incoming objects, and how it can take an object's property value and expand a collection into the pipeline. select-object has two additional command-line options, -first and - last , which instruct it to filter incoming objects passed solely on their sequence. This is similar to the head and tail commands found in other shells .
MSH C:\WINDOWS>
get-childitem select-object -first 10
Directory: FileSystem::C:\WINDOWS
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- Apr 24 16:04 1920054 BGInfo.bmp
-a--- Mar 25 04:00 1272 Blue Lace 16.bmp
-as Apr 24 15:47 2048 bootstat.dat
-a--- Apr 24 15:15 4348 certocm.log
-a--- Mar 25 04:00 82944 clock.avi
-a--- Mar 25 04:00 17062 Coffee Bean.bmp
-a--- Apr 24 15:15 16012 comsetup.log
-a--- Apr 24 14:58 0 control.ini
-a--- Mar 25 04:00 2 desktop.ini
-a--- Mar 25 04:00 56832 dialer.exe
MSH C:\WINDOWS>
get-childitem select-object -last 10
Directory: FileSystem::C:\WINDOWS
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- Apr 24 14:51 srchasst
d---- Apr 24 07:40 system
d---- Apr 24 19:05 system32
d---- Apr 24 07:40 TAPI
d---s Apr 24 15:20 Tasks
d---- May 22 14:42 Temp
d---- Apr 24 07:32 twain_32
d---- Apr 24 15:42 VMADD
d-r-- Apr 24 14:53 Web
d---- Apr 24 15:56 WinSxS
select-object has another option that can be used to filter the pipeline such that only unique objects are returned. When dealing with large amounts of data, it's sometimes convenient to see just the range of values rather than the actual values. For example, a typical call to get-service will return nearly 100 services, each with its own name and status. If we're interested only in seeing the different values of service state in this list, the - unique option can help:
MSH D:\MshScripts>
get-service select-object Status -unique
Status
------
Stopped
Running
This filtering of unique objects turns out to be quite useful. When the select-object -Unique cmdlet is placed in a pipeline, it will remove any duplicate objects. The first instance will be allowed to pass through, but any subsequent identical objects will be dropped:
MSH D:\MshScripts>
"aa","aa","bb" select-object -Unique
aa
bb
One other cmdlet that deserves a mention is measure-object . Think of this cmdlet as a universal tape measure; it can be used in any pipeline to give statistics about the objects that are moving through. When used without any options, it will just count the number of objects it sees. It becomes somewhat more interesting when the - Property option is used to measure a particular property of the incoming objects; when combined with some combination of the - Average , -Sum , -Min , and - Max options, measure-object will report some basic statistical analysis of the property:
MSH D:\MshScripts>
get-childitem measure-object
Count : 18
Average :
Sum :
Max :
Min :
Property :
MSH D:\MshScripts>
get-childitem measure-object -Property Length -Average -Sum -Min -Max
Count : 18
Average : 10492.1111111111
Sum : 188858
Max : 101546
Min : 0
Property : Length
5.1.2. What About...Can the commands head and tail be used instead of select-object and its options? Yes, but since it's important to also pass a parameter to the cmdlet, it is not possible to use an alias. Instead, functions can be used to call the cmdlet with the right parameters. As a bonus, Example 5-1 can also take a filename as a parameter, allowing usage like head longfile.txt -count 5 . Example 5-1. Simple head and tail functions
function head {
param($filename, $count = 10)
if ($filename) { $source = get-content $filename }
else { $source = $input }
$source select-object -first $count
}
function tail {
param($filename, $count = 10)
if ($filename) { $source = get-content $filename }
else { $source = $input }
$source select-object -last $count
}
De-duping simple arrays may not seem all that useful, but as we'll see in the next section, there are cmdlets that can take a text file from disk and put it into the pipeline line by line. Removing duplicate lines from a text file can be a more meaningful task. For example, consider parsing IIS logfiles in much the same way as we saw at the end of Chapter 3, except this time, let's do away with the hashtable and list the unique set of successfully requested URLs:
MSH D:\MshScripts>
filter ExtractUrl { $parts = $_.Split(" "); if ($parts[10] -eq 200) { $parts[4] } }
MSH D:\MshScripts>
get-content ex010101.log ExtractUrl select-object
-Unique
/default.aspx
/images/banner_bottom.gif
/images/banner_left.gif
/images/banner_right.gif
/images/banner_top.gif
/robots.txt
...
5.1.3. Where Can I Learn More?Built-in help continues to be the ever-present reference point for cmdlet syntax and options. In particular, take a look at some of the other parameters available on the select-object and measure-object cmdlets: there's more functionality there than meets the eye. |