Monday, January 5, 2015

Windows PowerShell Operators

Windows PowerShell Operators
 PowerShell is designed to be an interactive command-line shell, but it's also a programming language. As you advance in your PowerShell understanding and knowledge, it's inevitable you're going to run into a number of core computer programming concepts. Operators are one of these core programming concepts, and you've probably already been using them without necessarily knowing everything about them.
The term operator refers to one or more characters in a command or expression that PowerShell interprets in a specific way. For example, the addition operator is the + character, and PowerShell interprets the + character to mean addition. Operators depend on context. For example, the + character doesn't behave as the addition operator inside a quoted string. Also, not all operators are a single character (like +); some are multiple characters (such as -eq, -or, and -not).
PowerShell operators fall into a number of different categories. For example, arithmetic operators perform operations primarily on numbers, but they also affect strings and other data types. Along with the basic assignment, math, comparison, and logical operators, PowerShell has a number of operators that save time and coding effort (such as -like, -match, -replace, -contains, -split, and -join). Let's take a look at the different categories of operators and how to use them in PowerShell.
The Arithmetic Operators
The arithmetic operators consist of the following characters: + (add), - (subtract), * (multiply), / (divide), and % (modulus, or division remainder). These operators behave exactly as expected when using numbers. This means you can use PowerShell as a simple calculator by typing expressions at the PowerShell prompt. Figure 1 shows some simple examples.


PowerShell evaluates arithmetic expressions from left to right and according to the normal order of operations (multiplication, division, addition, then subtraction), unless you use parentheses for grouping. PowerShell ignores the spaces between the operators, so you can use spaces in your arithmetic expressions if it makes things clearer.
Besides working with numbers, the + and * operators work with strings, as shown in Figure 1. When you use the + operator, it concatenates strings. When you use the *operator, it repeats a string.
The Assignment Operators
The assignment operators assign values to variables or object properties. The most common assignment operator is =, which sets a variable or object property to a value. There are some other assignment operators as well: +=, -=, *=, /=, %=, ++, and --. These other assignment operators modify the value before assigning it. The commands in Figure 2 demonstrate some of the assignment operators.


The Comparison Operators
The comparison operators compare values in PowerShell. There are four kinds of comparison operators: equality, match, containment, and replace. Let's take a look at each of these.
Equality operators. The equality operators are equal (-eq), not equal (-ne), greater than (-gt), greater than or equal (-ge), less than (-lt), and less than or equal (-le). PowerShell doesn't use an equals sign (=) to test equality because it's used for the assignment operator. Similarly, PowerShell doesn't use the greater than (>) or less than (<) characters because they're used for output and input redirection, respectively.
All the equality operators return a Boolean value ($true or $false) that indicates the result of the comparison. For example, the expression
$var -eq 5
returns $true if $var contains 5 or $false otherwise.
Match operators. The match operators are -like, -notlike, -match, and -notmatch. These operators perform pattern matching. The -like and -notlike operators use wildcards characters (? and *), whereas the -match and -notmatch operators use regular expressions. These operators return a Boolean value ($true or $false), depending on whether the expression on the left side of the operator matches (or doesn't match) the expression on the right side of the operator. Figure 3 shows the match operators in action.


Containment operators. There are two containment operators: -contains and -notcontains. These operators return a Boolean value ($true or $false) depending on whether the value on the right side of the operator exists (or doesn't exist) in the set of values on the left side of the operator. These operators provide a convenient way to see if a value exists in an array. For example, the expression
"A","B","C" -contains $str
returns $true if $str contains the character A, B, or C (case insensitive). If the expression on the left side is a single value (rather than an array), the -contains and -notcontains operators work the same way as the -eq and -ne operators, respectively.
Replace operator. The -replace operator replaces a pattern in an input value using a regular expression. This operator uses two arguments (separated by a comma): a regular expression pattern and its replacement value. For example, the expression
"The rain in Seattle" -replace "rain","hail"
returns the string "The hail in Seattle". As noted, the -replace operator also works with regular expressions, so the PowerShell expression
"kenmyer@contoso.com" -replace '^[\w]+@(.+)', '$1'
returns the string "contoso.com". If you're unfamiliar with regular expressions, the PowerShell Help topic about_Regular_Expressions provides a good introduction.
By default, all the PowerShell comparison operators (as well as the split operator, which I'll describe in a moment) are case insensitive. If you want a case-sensitive version of the operator, prefix it with the letter c. For example, -ceq is the case-sensitive version of -eq, -creplace is the case-sensitive version of -replace, and -csplit is the case-sensitive version of -split. Technically, PowerShell also supports using the prefix i to specify case-insensitive operators (e.g., -ieq, -ireplace, and -isplit), but this prefix is rarely used because these operators are case insensitive by default.
The Split and Join Operators
The -split operator splits a string into an array of substrings. The -join operator is its inverse—it joins an array of strings into a single string. The -split and -join operators make converting a string into an array (or vice versa) a snap. Both operators let you specify one or more delimiter characters that define how PowerShell should split or join the string. Figure 4 shows some examples of how you can use these operators.


The Logical Operators
You can use the logical operators to connect expressions or statements together to form a single expression. These operators are -and, -or, -xor, -not, and ! (! is the same as -not). Just as with the arithmetic operators, you can use parentheses in your expressions to coerce PowerShell to evaluate them in the order you want. These operators work like you would expect in other programming languages. For example, the expression
($var + 3 -eq 6) -or ($var - 3 -eq 0)
returns $true if $var contains 3.
PowerShell stops evaluating the expressions on either side of a logical operator once it gets a $true result. This is sometimes called short-circuit evaluation. The Test-Truth.ps1 script in Listing 1 demonstrates how PowerShell uses short-circuit evaluation.
Listing 1: Test-Truth.ps1
function AddOne($number) {
  $number++
  write-host "AddOne: $number"
  $number  # Output result
}

function SubtractOne($number) {
  $number--
  write-host "SubtractOne: $number"
  $number  # Output result
}

$number = 1

write-host "Short-circuit evaluation:"
# Example of short-circuit evaluation: The expression
# on the left side of the -or operator is $true, so
# PowerShell doesn't need to evaluate the expression
# on the right side of the -or operator.
(AddOne $number) -eq 2 -or (SubtractOne $number) -eq 0
# Outputs "AddOne: 2" and "True", but doesn't output
# "SubtractOne: 0".

write-host
# PowerShell must evaluate the expressions on both sides
# of the -and operator to determine whether the entire
# expression is $true or $false.
(AddOne $number) -eq 2 -and (SubtractOne $number) -eq 0
# Outputs "AddOne: 2", "SubtractOne: 0", and "True".
In the script, the AddOne and SubtractOne functions both use the Write-Host cmdlet. Based on the script's output, you can clearly see when PowerShell calls (and doesn't call) the functions.
The Type Operators
The type operators are -is and -isnot. These operators test whether the value on the left side of the operator is (or isn't) a specific Microsoft .NET type. For example, the expression
3 -is [Int]
returns $true, whereas the expression
"fabrikam" -isnot [String]
returns $false.
The Redirection Operators
The redirection operators are listed in Table 1. As you can see, many new redirection operators were introduced in PowerShell 3.0. At this time, PowerShell supports only output redirection, but it might support input redirection in a future version.
Table 1: PowerShell Redirection Operators
Operator
Description
Available In
> 
Redirects standard (non-error) output to a file
All PowerShell versions
>> 
Redirects output and appends it to a file
All PowerShell versions
2>
Redirects error output to a file
All PowerShell versions
2>>
Redirects error output and appends it to a file
All PowerShell versions
2>&1
Redirects error output to the same location as standard output
All PowerShell versions
3>
Redirects warning output to a file
PowerShell 3.0 and later
3>>
Redirects warning output and appends it to a file
PowerShell 3.0 and later
4>
Redirects verbose output to a file
PowerShell 3.0 and later
4>>
Redirects verbose output and appends it to a file
PowerShell 3.0 and later
5>
Redirects debug output to a file
PowerShell 3.0 and later
5>>
Redirects debug output and appends it to a file
PowerShell 3.0 and later
n>&1
Redirects warning (n = 3), verbose (n = 4), or debug (n = 5) output to the same location as standard output
PowerShell 3.0 and later
*>
Redirects all output streams (standard, errorwarning, verbose, and debug) to a file
PowerShell 3.0 and later
*>>
Redirects all output streams and appends them to a file
PowerShell 3.0 and later
The redirection operators are easy to use. For example, if you want to redirect the Get-ChildItem cmdlet's output to the file Output.txt, you'd run the command:
Get-ChildItem C:\,nofile > Output.txt 2>&1
The Output.txt file will also contain error messages.
When using redirection operators, it's important to remember that PowerShell writes to the output file using Unicode text. If you don't want Unicode output, you can use the Out-File cmdlet instead of the > or >> operators.
The Special Operators
PowerShell's special operators are a collection of operators that don't fall into other categories. There are nine special operators:
The invocation (&) operator. The & operator runs a command, script, or script block. (PowerShell's documentation also refers to it as the call operator.) This operator tells PowerShell that the expression that follows is something it should run.
When using PowerShell interactively, you need to use the & operator to run a program that contains spaces in its name or path. For example, if you use the command
"C:\Program Files (x86)\Test App\MyApp.exe"
PowerShell doesn't start the program MyApp.exe. It just displays the string onscreen. If you want to run MyApp.exe as a program, you need to place the & operator before the string:
& "C:\Program Files (x86)\Test App\MyApp.exe"
The property dereference (.) operator. You use the property dereference operator to indicate that the expression on the left side of the dot character is an object and the expression on the right side is an object member (a property or method). For example, $file.Name refers to the Name property of the object in the $file variable.
The dot sourcing (.) operator. You can also use the dot character to run a script in the current scope. Normally when you run a script, PowerShell creates a new scope for the script—that is, the variables and functions the script creates are discarded when the script terminates. If you don't want PowerShell to create a new scope when you run a script, you need to prefix the script with the dot sourcing operator. For example, suppose you have a list of useful functions in the script file MyFunctions.ps1. You can use the dot sourcing operator to load the scripts:
. MyFunctions.ps1
The functions defined in MyFunctions.ps1 will now be available after the script terminates.
The static member (::) operator. To access a static member of a .NET class, you can use the static member operator. A class is a type of object, and a static member is a property or method of a class. For example, the expression
[DateTime]::Now
refers to the Now static property of the DateTime .NET class.
The range (..) operator. The range operator returns an array of integers represented by the lower and upper bounds of the integers on either side of the two consecutive dots. For example, the expression 1..3 outputs a three-element array (1, 2, 3), and the expression 9..6 outputs a four-element array (9, 8, 7, 6).
The format (-f) operator. The -f operator formats a string based on .NET string formatting rules. The input string (i.e., the string on the left side of the -f operator) should include substrings containing curly braces and an expression index, as in {0:N2}. The -f operator accepts an array on its right side, so the first number after the opening curly brace in the substring tells PowerShell which array element to format (0 for the first element, 1 for the second, and so forth). For example, the expression
"{0:N1} and {1:N2}" -f (100/3),(76/3)
returns the string "33.3 and 25.33". That is, the first expression (index 0) after -f (100/3) will be formatted with formatting code N1 (one decimal place), and the second expression (index 1) after -f (76/3) will be formatted with formatting code N2 (two decimal places). For information about the formatting codes, see MSDN's Formatting Types web page.
The subexpression operator. The $( ) operator causes PowerShell to evaluate the expression in between the $( and the ) characters. This operator is helpful when you want to force PowerShell to evaluate an expression inside a quoted string, such as when you want to get an object's property. For example, suppose you have a variable $myString that contains the string "KenDyer". The expression
"$myString is $myString.Length characters long"
will output "KenDyer is KenDyer.Length characters long", which is probably not what you intended. To solve this, you can use the $( ) operator to get the desired result. In this example, the expression
"$myString is $($myString.Length) characters long"
will output the result you were probably expecting ("KenDyer is 7 characters long").
The array subexpression operator. The @( ) operator is useful when you have some data (such as an object property or the output of a function or method) that might be empty, a single value, or an array. For example, an Active Directory (AD) group might have no members, a single member, or multiple members. The subexpression operator coerces the data into an array to make processing easier. To demonstrate, I created the Test-Array.ps1 script in Listing 2.
Listing 2: Test-Array.ps1
# Returns nothing
function Null {
}

# Returns a single item
function SingleItem {
  "A"
}

# Returns multiple items
function MultipleItems {
  "A","B","C"
}

$testVar = @(Null)
$numElements = $testVar.Count
"Number of elements: $numElements"
# Outputs "Number of elements: 0"

$testVar = @(SingleItem)
$numElements = $testVar.Count
"Number of elements: $numElements"
# Outputs "Number of elements: 1"

$testVar = @(MultipleItems)
$numElements = $testVar.Count
"Number of elements: $numElements"
# Outputs "Number of elements: 3"
This script contains three functions: Null (which returns nothing), SingleItem (which returns a single item), and MultipleItems (which returns multiple items). When the script calls each function, it uses @( ) around each function call to ensure that the $testVar variable contains an array, no matter how many items are returned from the function. If the script didn't use @( ) when calling the functions, it wouldn't work as expected because the Count property would be different based on the objects returned from the functions. For example, SingleItem returns a single string; strings don't have a Count property, so the $numElements variable would be $null. Using @( ) helps the script maintain consistency, regardless of the number of elements returned from any of the functions.
The comma (,) operator. If you place the comma operator before a single value, you can create a one-element array. For example, the expression
$items = ,"A"
assigns a one-element array to the variable $items. You can also place the comma operator between items in a list to create a multiple-element array. For example, the expression
$items = "A","B","C"
assigns a three-element array to the variable $items.
Know Your Operators
As you can see, PowerShell has a long list of operators. The PowerShell Help topics, starting with about_Operators, does a good job of introducing the different categories of operators and providing examples. A good understanding of PowerShell's operators is a must if you want to increase your understanding of PowerShell and the efficiency of your code.