Powershell Cheat Sheet

Saturday, June 21, 2014

Strings

Strings in single quotes are simple strings. They don’t support escaping, so they can’t contain other single quotes.

Strings in double quotes support expansion: any variable can be included in the string if prefixed with a dollar sign $. If $a has the value ‘there’, the string “Hello $a” evaluates to ‘Hello there’. Complete expressions can be expanded, too, but they have to be enclosed in parentheses, as in “Hello $(expression)”.

Double quoted string als support escaping with the backtick-character ` for special characters like the double quote, the dollar sign and the backtick itself. A single backtick at the end of the line is used for line continuation, and `r `n `b `f `t are the usuals: CR, LF, BS, FF, TAB.

Both single and double quoted string can span multple lines. An end-of-line is translated into a CR (`r).

A here-string is a special case of a multi-line string. Their declaration starts with @” at the end of a line and ends with “@ on a line of its own, as in:

$herestring = @"
This is a here-string, which can contain unescaped quotes,
spanning multiple lines.

Supports backtick escape sequences like `r and `n
"@

In this example, the string does not start with an en-of-line, nor does it end in one. The EOL right after the opening @” is not included and neither is the EOL before the closing “@.

Here-strings don’t need escaping for double quotes, nor for CR and/or LF. Note: an embedded EOL in a here-string is a CR (`r), not a CRLF (`r`n)

The single-quoted here-string, like the normal single-quoted string, does not support expansion, nor escaping.

Note: Powershell treats all text as strings of the double-quoted kind, so the following two statements are equivalent:

echo TEST$b
echo "Test$b"

Both expand the variable $b. If that variable doesn’t exist, an empty string is expanded – in effect removing the variable from the string.

String formatting

Syntax:

format-string -f value[, value, ...]

Example:

"{0}: {1}" -f 123, 'abcdefg' # result: 123: abcdefg

String arrays

When string arrays are converted to a string, the elements are joined on a single line, separated by spaces:

[string]("a", "b") # --> a b

The opposite is not true: strings are not split when assigning to an array:

[string[]]"a b c" # --> one element: "a b c"

A string can be split on spaces, tabs, CR and LF using the Split() function:

"a b=c `rc`nd`te`bf".Split() --> ("a", "b=c", "c", "d", "ef")

Piping

Powershell makes heavy use of piping to filter, sort and format objects. The generic form is: Some-Command | Where-Object { condition } | Sort-Object PropertyName | Select-Object PropertyName

  • Some-Command is the source of the pipeline: its output is passed into the pipeline.
  • Where-object filters object from the pipeline based on some condition, usually a code block enclosed in curly braces (short form: ?). The special variable $_ refers to the current object in the code block
  • Sort-Object sorts the object in the pipeline by one or more properties (short form: sort)
  • Select-Object selects one or more properties from each object in the pipeline (short form: select)

Example: alias | ? { $_.DisplayName.Startswith(‘s’) } | sort Name -Descending

Argument passing

Arguments to commands and functions are passed separated by spaces, not comma’s. Comma’s create a single argument consisting of an array of values! If Test is defined like

function Test($x) { $x + 1 }

then calling

Test 2 # 3 - OK
Test 1, 2 # Equals Test (1,2)
Test (1,2) # Unexpected: (1,2,1)! (1,2) + 1 = (1,2,1)

For / Each

There are two for’s in Powershell:

  • The C-version: for ($a = 0; $a -lt 10; $a++) { echo $a } prints 0 to 9
  • The C#-version: foreach ($a in 1..10) { echo $a } prints 1 to 10. This version can also be used with piping: 1..10 | foreach { echo $_ } prints 1 to 10. This version can be abbreviated to %

Ranges

1..10 signifies the range of integers from 1 to 10, inclusive:

1..10 # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Array indexing

Ranges can be used to index arrays (and therefore strings, which are arrays of character):

"abc"[1..2] # ("b", "c")

But array indexing is more powerful than that:

"abc"[0,2,1] # ("a", "c", "b")

And negative numbers index from the end:

"abcdef"[-2..-1] # ("e", "f")

Variables

All variables are prefixed with a dollar sign. They cannot be declared: a variable is automatically created when it is first used. (Techinically, you can call New-Variable to create a variable with or without a value, but since there's no way to specify its type there usually is no need to do it that way). So:

$x = 1 # Declares a variable named x whose value is 1
$y = 'test' # Declares y to be a string with the value "test"

Typing variables

When declaring variables this way, the are basically typeless. Internally they may be of type Object or Dynamic or whatever, but the effect is that it's allowed to assign the variable a value of a completely different type:

$x = "abc" # Allowed - x becomes a string now

By the way, it's easy to see a variables current type:

$x.GetType().Name # "String"

This is the variable's current type, because:

$x = 2.5
$x.GetType().Name # "Double"

To work type-safely, you can declare a variable with a type:

[int]$x = 2 # Declares x to be an integer with value 2

Interestingly, this now doesn't work anymore:

$x = "abc" # Error: Cannot convert value "abc" to type "System.Int32"

By declaring the variable's type, it's fixed to integer. It is, however, possible to re-type a variable:

[double]$x = 2 # x is now a double with value 2.5

The same type syntax can be used on any expression, but then it performs type casting:

[int]3.5 # 4
[int]2.5 # 2 (!)

Both lines take a double value (3.5 and 2.5) and convert them to int. (Note how the conversion not only rounds, but rounds toward even - i.e. rounding "half" values rounds up or down to achieve an even outcome. This is the default in .NET, which was a surprise to me when I first found out!)

This leads to a strange-looking possibility:

[double]$x = 2.5
[int]$x = $x # Converts the value 2.5 to int and types x as int