You'll need a condition first to compose intelligent PowerShell code capable of making decisions. That's why you'll learn in the first part of this Chapter how to formulate questions as conditions. In the second part, you'll employ conditions to execute PowerShell instructions only if a particular condition is actually met. Topics Covered: Formulating ConditionsA condition is nothing more than a question that can be answered clearly in the positive (true) or in the negative (false). Nearly all questions are phrased with the help of comparisons. The following PowerShell comparison operators allow you to compare values:
Table 7.1: Comparison operators PowerShell doesn't use the traditional comparison operators that you may know from other programming languages. In particular, the "=" operator is purely an assignment operator in PowerShell, while ">" and "<" operators are used for redirection. There are three variants of all comparison operators. The basic variant is case-insensitive when making comparisons. If you'd like to explicitly specify whether case sensitivity should be taken into account, use variants that begin with "c" (case-sensitive) or "i" (case-insensitive). Carrying Out a ComparisonYou can carry out comparisons immediately and directly in the PowerShell console. First, enter a value, then a comparison operator, and then the second value that you want to compare with the first. As soon as you hit (enter), the comparison will be performed. The result should always be True (condition is correct) or False (condition is incorrect). 4 -eq 10
False
"secret" -ieq "SECRET"
True
As long as you compare only numbers or only strings, comparisons are very easy to grasp and return exactly the result that you expect: 123 -lt 123.5
True
However, you can also compare different data types. These results are not always as logical as the previous one: 12 -eq "Hello"
False
12 -eq "000012"
True
"12" -eq 12
True
"12" -eq 012
True
"012" -eq 012
False
123 -lt 123.4
True
123 -lt "123.4"
False
123 -lt "123.5"
True
Would you have expected these results? Some comparisons return peculiar results. That's precisely what happens when you compare different data types, and the reason is that PowerShell actually cannot compare different data types at all. PowerShell tries to convert the data types into a common data type that can be compared. However, this automatic conversion doesn't always return the result that you would intuitively expect, so you should avoid comparisons of differing data types. "Reversing" ComparisonsA comparison always returns a result that is either true or false, and you've seen that there are complementary comparison operators for most comparisons: -eq and -ne (equal and not equal) or -gt and -lt (greater than and less than). In addition, with the logical operator -not you have the option of "reversing" the result of a comparison. It expects an expression on the right side that is either true or false, and it turns this around. Instead of -not, you may also use the abbreviated "!": $a = 10
$a -gt 5 True
-not ($a -gt 5)
False
# Shorthand: instead of -not "!" can also be used:
!($a -gt 5) False
Make generous use of parentheses if you're working with logical operators like -not. Logical operators are always interested in the result of a comparison, but not in the comparison itself. That's why the comparison should always be in parentheses. Combining ComparisonsBecause every comparison returns either True or False, you can combine several comparisons with logical operators. The following conditional statement would evaluate to true only if both comparisons evaluate to true: ( ($age -ge 18) -and ($sex -eq "m") )
Put separate comparisons in parentheses because you only want to link the results of these comparisons, certainly not the comparisons themselves.
Table 7.2: Logical operators Comparisons with Arrays and CollectionsUp to now, you've only used the comparison operators in Table 7.1 to compare single values. In Chapter 4, you've already become familiar with arrays. The question is: how do comparison operators react to arrays? To which element of an array is the comparison applied? The simple answer: to all of them. But the result is not a long list of True and False. In this case, comparison operators return an array in which precisely those elements of the initial array reappear in the matched comparison—resembling a sort of filter. In the simplest case, use the comparison operator -eq (equal) to find all elements in an array equal to the specified value: 1,2,3,4,3,2,1 -eq 3
3
3 Two elements having the value of 3 are in the initial array. Only these two elements were returned. It works conversely, too: if you'd like to see only the elements of an array that don't match the comparison value, use -ne (not equal) operator: 1,2,3,4,3,2,1 -ne 3
1
2 4 2 1 Verifying Whether an Array Contains a Particular ElementHow can you find out whether an array contains a particular element? As you have seen, -eq provides no answer to this question. That's why there are the comparison operators -contains and -notcontains. They verify whether a certain value exists in an array. # -eq returns only those elements matching the criterion:
1,2,3 -eq 5 # -contains answers the question of whether the sought element is included in the array:
1,2,3 -contains 5 False
1,2,3 -notcontains 5
True
Where-ObjectLet's now apply conditions in real life. The first area of application is the PowerShell pipeline, which you became acquainted with in Chapter 5. In the pipeline, the results of a command are forwarded directly to the next one, and the Where-Object cmdlet works like a filter, allowing only those objects through the pipeline that meet a certain condition. To make this work, specify your condition to Where-Object. Filtering Results in the PipelineThe cmdlet Get-Process, will return all running processes. However, you are not likely to be interested in all processes, but instead you want an answer to a specific problem. For instance, you would like to find out currently running instances of the Notepad. First, get an initial overview of which properties the processes contain by using Get-Process. That's important, because you'll use these properties afterwards as the basis for your condition. This is how you can find the available properties:
Formulating a ConditionThe name of a process can be found in the Name property. If you're just looking for the processes of the Notepad, your condition should be name -eq 'notepad'. Now, supply this condition to Where-Object: Get-Process | Where-Object { $_.name -eq 'notepad' }
The pipeline now returns only those processes that meet your condition. If you're not currently running the Notepad, nothing will be returned. If you take a closer look at Where-Object, you'll see that your condition is specified in braces after the cmdlet. The $_ variable contains the current pipeline object. The next one-liner would retrieve all processes whose company name begins with "Micro" and output for each process its name, description, and company name: Get-Process | Where-Object { $_.company -like 'micro*' } |
Format-Table name, description, company
In Chapter 6 you learned that every single process in this list is actually an object that not only has the properties that you just made visible in the previous example, but also has methods. That means you could go on to process the result of your condition object by object and, in doing so, invoke methods for every object. To do so, you need loops, which will be explained in more detail in the next Chapter. However, for the time being, here's a little preview: the next line ends all Notepad processes. Watch out: the processes will be ended immediately and without request for confirmation. All data that you haven't saved will be lost: # Attention: all instances of Notepad will be terminated
# immediately and without further notification: Get-Process | Where-Object { $_.name -eq 'notepad' } | Foreach-Object { $_.Kill() } Using AliasBecause you often need conditions in the pipeline, an alias exists for Where-Object: "?". So, instead of Where-Object, you may also use "?'". # The two following instructions return the same result:
# all running services Get-Service | ForEach-Object {$_.Status -eq 'Running' } Get-Service | ? {$_.Status -eq 'Running' } If-ElseIf-ElseWhere-object works splendidly in the pipeline, but it is inappropriate if you want to make longer code segments dependent on meeting a condition. Here, the If..ElseIf..Else statement works much better. In the simplest case, the statement looks like this:
The condition must be enclosed in parentheses and follow the keyword If. If the condition is met, the code in the braces after it will be executed, otherwise not. Try it out: If ($a -gt 10) { "$a is larger than 10" } It's likely, though, that you won't (yet) see a result. The condition was not met, and so the code in the braces wasn't executed. To get an answer, make sure that the condition is met:
11 is larger than 10
Now the comparison is correct, and the If statement ensures that the code in the braces returns a result. As it is, that clearly shows that the simplest If statement usually doesn't suffice in itself, because you would like to always get a result, even when the condition isn't met. To accomplish that, expand the If statement with Else: If ($a -gt 10)
{ "$a is larger than 10" } Else { "$a is less than or equal to 10" } Now the code in the braces after If is executed if the condition is met; if the preceding condition isn't true, the code in the braces after Else is executed. If you have several conditions you may insert as many ElseIf blocks between If and Else as you like:
The If statement here always executes the code in the braces after the condition that is met. The code after Else will be executed when none of the preceding conditions are true. What happens if several conditions are true? Then the code after the first applicable condition will be executed and all other applicable conditions will be ignored.
The fact is that the If statement doesn't care at all about the condition that you state. All that the If statement evaluates is $true or $false. If condition evaluates $true, the code in the braces after it will be executed, otherwise not. Conditions are only a way to return one of the requested values $true or $false. But the value could come from another function or from a variable:
The example shows that the condition after If must always be in parentheses, but it can also come from any source as long as it is $true or $false. In addition, you may also write the If statement in a single line. If you'd like to execute more than one command in the braces without having to use new lines, separate the commands with a semicolon ";". SwitchIf you'd like to test a value against many comparison values, the If statement could quickly become confusing. The Switch statement is much clearer and quicker:
This is how to use the Switch statement: the value to switch on is in the parentheses after the Switch keyword. That value is matched with each of the conditions case by case. If a match is found, the action associated with that condition is performed. Default comparison operator is the -eq operator to verify equality. Testing Range of ValuesThe default comparison operator is -eq operator, but you could also compare a value with your own conditions. Formulate your own condition and put it in braces. Condition must result in either true or false:
Here, you used the initial value stored in $_ for your conditions, but because $_ is generally available anywhere in the Switch block, you could just as well have put it to work in the result code:
No Applicable ConditionIn a similar manner as an If statement, the Switch statement executes code only if at least one of the specified conditions is met. The keyword, which for the If statement is called Else, is called default for Switch statement. When no other condition matches, the default clause is run.
Several Applicable ConditionsIf more than one condition applies, then Switch will behave differently than If. For If, only the first applicable condition was executed. For Switch, all applicable conditions are executed:
Consequently, all applicable conditions ensure that the following code is executed, and so in some circumstances you may get more than one result. Try out that example, but assign 50.0 to $value. In this case, you'll get just two results instead of three. Do you have any idea why? That's right: the third condition is no longer fulfilled because the number in $value is no longer an integer number. The other two conditions, however, remain fulfilled. If you'd like to receive only one result, while consequently making sure that only the first applicable condition is performed, then append the break statement to the code.
In fact, now you get only the first applicable result. The keyword break indicates that no more processing will occur and the Switch statement will exit. Using String ComparisonsThe previous examples have always compared numbers. You could also naturally compare strings since you now know that behind the scenes Switch uses only the normal -eq comparison operator and that there string comparisons are also permitted. The following code could be the basic structure of a command evaluation. A different action will be performed, depending on the specified command:
Case SensitivitySince the -eq comparison operator doesn't distinguish between lower and upper case, case sensitivity doesn't play any role in comparisons. If you want to distinguish between them, then use the -case option. Working behind the scene, it will replace the -eq comparison operator with -ceq, after which case sensitivity will suddenly become crucial:
Wildcard CharactersIn fact, you can also exchange a standard comparison operator for -like and -match operators and then carry out wildcard comparisons. Using the -wildcard option, activate the -like operator, which is conversant, among others, with the "*" wildcard character:
Regular ExpressionsSimple wildcard characters can't always be used for recognizing patterns. Regular expressions are much more efficient. But they assume much more basic knowledge, a reason for you to now take a peek ahead at Chapter 13, which discusses regular expression in greater detail. With the -regex option, you can ensure that Switch uses the -match comparison operator instead of -eq, and thus employs regular expressions. Using regular expressions, you can identify a pattern much more precisely than by using simple wildcard characters. But that's not all: as was the case with the -match operator, you will usually get back the text that matches the pattern in the $matches variable. This way, you could even parse information out of the text:
The result of the -match comparison with the regular expression is returned in $matches, a hash table with each result, because regular expressions can, depending on their form, return several results. In the example, only the first result should interest you, the one you got by using $matches[0]. To ensure that this result appears in the output text, the entire expression is embedded in $(...). Processing Several Values SimultaneouslyUntil now, you have always passed to Switch just one value for evaluation. But Switch can also process several values at the same time. To do so, pass to Switch the values in an array or a collection. In the following example, Switch is passed an array containing five elements. Switch automatically takes all the elements one at a time from the array and compares each of them, one by one:
There you have it: Switch accepts not only single values but also entire arrays and collections. As such, Switch would actually be an ideal candidate for evaluating results on the PowerShell pipeline because the pipeline character ("|") is used to forward results as arrays or collections from one command to the next. The next line queries Get-Process for all running processes and pipes the result to a script block (& {...}). In the script block, Switch evaluates the result of the pipeline, which is available in $input. If the WS property of a process is larger than one megabyte, this process is output Switch will filter all the processes whose WS property is less than or equal to one megabyte:
However, this line is extremely hard to read and seems complicated. By using Where-Object, you can formulate the condition in a much clearer way:
This variant is also quicker because Switch had to wait until the pipeline had collected the entire results of the preceding command in $input. In Where-Object, it processes the results of the preceding command precisely when the results are ready. This difference is especially striking for elaborate commands:
SummaryIntelligent decisions are based on conditions, which in the simplest form can be reduced to plain Yes or No answers. Using the comparison operators listed in Table 7.1, you can formulate such conditions and can even combine these with the logical operators listed in Table 7.2 to form complex queries. The simple Yes/No answers of your conditions determine whether particular PowerShell instructions should be carried out or not. In the simplest form, you can use the Where-Object cmdlet in the pipeline. It functions there like a filter, allowing only those results through the pipeline that correspond to your condition. If you would like more control, or would like to execute larger code segments independently of conditions, use the If statement, which evaluates as many different conditions as you wish and, depending on the result, executes the allocated code. This is the typical "If-Then" scenario: if certain conditions are met, then certain code segments will be executed. An alternative to the If statement is the Switch statement: using it, you can compare a fixed initial value with various possibilities. Switch is the right choice when you want to check a particular variable against many different possible values. |
手机版|小黑屋|BC Morning Website ( Best Deal Inc. 001 )
GMT-8, 2025-8-25 17:18 , Processed in 0.017280 second(s), 16 queries .
Supported by Best Deal Online X3.5
© 2001-2025 Discuz! Team.