Problem
You want to find an easier or more compact way to represent a large if ... elseif ... else conditional statement.
Solution
Use PowerShell’s switch statement to more easily represent a large if ... elseif ... else conditional statement.
For example:
$temperature = 20 switch($temperature)
{ { $_ lt 32 } 32 { $_ le 50 } { $_ le 70 } default }
{ "Below Freezing"; break }{ "Exactly Freezing"; break }{ "Cold"; break }{ "Warm"; break }{ "Hot" }
Discussion
PowerShell’s switch statement lets you easily test its input against a large number of comparisons. The switch statement supports several options that allow you to configure how PowerShell compares the input against the conditions—such as with a wildcard, regular expression, or even arbitrary script block. Since scanning through the text in a file is such a common task, PowerShell’s switch statement supports that directly. These additions make PowerShell switch statements a great deal more powerful than those in C and C++.
Although used as a way to express large conditional statements more cleanly, a switch statement operates much like a large sequence of if statements, as opposed to a large sequence of if ... elseif ... elseif ... else statements. Given the input that you provide, PowerShell evaluates that input against each of the comparisons in the switch statement. If the comparison evaluates to true, PowerShell then executes the script block that follows it. Unless that script block contains a break statement, PowerShell continues to evaluate the following comparisons.
Repeat Operations with Loops in Windows PowerShell
Problem
You want to execute the same block of code more than once.
Solution
Use one of PowerShell’s looping statements (for, foreach, while, and do), or PowerShell’s ForeachObject cmdlet to run a command or script block more than once. For example:
for loop for($counter = 1; $counter le 10; $counter++) { "Loop number $counter" }
foreach loop foreach($file in dir) { "File length: " + $file.Length }
ForeachObject cmdlet GetChildItem | ForeachObject { "File length: " + $_.Length }
while loop $response = "" while($response ne "QUIT") { $response = ReadHost "Type something" }
do..while loop $response = "" do { $response = ReadHost "Type something" } while($response ne "QUIT")
Discussion
Although any of the looping statements can be written to be functionally equivalent to any of the others, each lends itself to certain problems.
You usually use a for loop when you need to perform an operation an exact number of times. Because using it this way is so common, it is often called a counted for loop.
You usually use a foreach loop when you have a collection of objects and want to visit each item in that collection. If you do not yet have that entire collection in memory (as in the dir collection from the foreach example above), the ForeachObject cmdlet is usually a more efficient alternative.
Unlike the foreach loop, the ForeachObject cmdlet allows you to process each element in the collection as PowerShell generates it. This is an important distinction; asking PowerShell to collect the entire output of a large command (such as GetContent hugefile.txt) in a foreach loop can easily drag down your system.
A handy shortcut to repeat an operation on the command line is: PS >1..10 | foreach { "Working" } Working
Working Working Working Working Working Working Working Working Working
The while and do..while loops are similar, in that they continue to execute the loop as long as its condition evaluates to true.A while loop checks for this before ever running your script block, while a do..while loop checks the condition after running your script block.
Add a Pause or Delay in PowerShell
Problem
You want to pause or delay your script or command.
Solution
To pause until the user presses ENTER, use the ReadHost cmdlet:
PS >ReadHost "Press ENTER" Press ENTER:
To pause until the user presses a key, use the ReadKey() method on the $host object: PS >$host.UI.RawUI.ReadKey() To pause a script for a given amount of time, use the StartSleep cmdlet: PS >StartSleep 5 PS >StartSleep Milliseconds 300
Discussion
When you want to pause your script until the user presses a key or for a set amount of time, the ReadHost and StartSleep cmdlets are the two you are most likely to use. In other situations, you may sometimes want to write a loop in your script that runs at a constant speed—such as once per minute, or 30 times per second. That is typically a difficult task, as the commands in the loop might take up a significant amount of time, or even an inconsistent amount of time.
In the past, many computer games suffered from solving this problem incorrectly. To control their game speed, game developers added commands to slow down their game. For example, after much tweaking and fiddling, the developers might realize that the game plays correctly on a typical machine if they make the computer count to one million every time it updates the screen. Unfortunately, these commands (such as counting) depend heavily on the speed of the computer. Since a fast computer can count to 1 million much more quickly than a slow computer, the game ends up running much quicker (often to the point of incomprehensibility) on faster computers!
To make your loop run at a regular speed, you can measure how long the commands in a loop take to complete, and then delay for whatever time is left, as shown in Example 41.
Example 41. Running a loop at a constant speed
$loopDelayMilliseconds = 650 while($true) {
$startTime = GetDate
## Do commands here
"Executing"
$endTime = GetDate $loopLength = ($endTime $startTime).TotalMilliseconds $timeRemaining = $loopDelayMilliseconds $loopLength
if($timeRemaining gt 0) { StartSleep Milliseconds $timeRemaining } }
For more information about the StartSleep cmdlet, type GetHelp StartSleep.
Strings and Unstructured Text in PowerShell
Creating and manipulating text has long been one of the primary tasks of scripting languages and traditional shells. In fact, Perl (the language) started as a simple (but useful) tool designed for text processing. It has grown well beyond those humble roots, but its popularity provides strong evidence of the need it fills.
In textbased shells, this strong focus continues. When most of your interaction with the system happens by manipulating the textbased output of programs, powerful text processing utilities become crucial. These text parsing tools such as awk, sed, and grep form the keystones of textbased systems management.
In PowerShell’s objectbased environment, this traditional tool chain plays a less critical role. You can accomplish most of the tasks that previously required these tools much more effectively through other PowerShell commands. However, being an objectoriented shell does not mean that PowerShell drops all support for text processing. Dealing with strings and unstructured text continues to play an important part in a system administrator’s life. Since PowerShell lets you to manage the majority of your system in its full fidelity (using cmdlets and objects,) the text processing tools can once again focus primarily on actual text processing tasks.