The Complete Guide to PowerShell Punctuation

It is the punctuation, the strange dollar signs, brackets and parentheses that bewilder anyone learning PowerShell. Add to that the aliases and you can bewilder everyone. The punctuation is essential, so here is the the complete PowerShell wallchart and guide to Powershell Punctuation. PowerShell need no longer be perplexing.

PowerShell is both a powerful command-line shell and a scripting language, providing the full richness of the .NET framework in an interactive environment. PowerShell is useful for administrators and developers of varying skill levels. Though it requires effort to learn, you can be quite productive with PowerShell after gaining  only a small proportion of the skills and then acquiring more incrementally as you need to. Probably the most oft-cited hurdle of getting up to speed with PowerShell is learning the syntax and, in particular, the punctuation. If you review articles on PowerShell (mine included) you will often see a reader comment to the effect, “Good stuff but you don’t really explain what [X] is…” where X might be “% { ... }” or “$_” or “$($process.name)” or many other quirky-looking expressions. Every writer makes assumptions about what basic information a reader will know coming in, but unfortunately that leaves occasional knowledge gaps leading to the sort of comment I have indicated.

2289-imgC6.jpg

This reference is an attempt to tackle that knowledge gap. Whether you keep it bookmarked, keep it taped to your monitor, or keep it tucked under your pillow, just make sure it is within arm’s reach the next time you open a new PowerShell article to read, so the lexicon herein will let you translate, or comprehend, whatever the author is throwing at you. If you have a burning need to know what a particular character is doing in an article you are reading now, jump right to the attached wallchart to find out. Otherwise, I encourage you to start with this short introduction that provides just a bit more context than the wallchart allows space for.

Expressions

Though sometimes an expression may stand alone (you could just type 5 + 3, for example, and press return to evaluate that expression), parentheses are often a key element to an expression in PowerShell. The catch is noticing what comes just before: is it just parentheses or is the opening parenthesis preceded by a dollar sign $ or at-sign @ ?

(...)

Plain parentheses act as a grouping expression to encapsulate a single cmdlet or a single sequence, where a sequence might be something piped to something else that is  piped to something else again. The output of a sequence comes only from the terminal command or cmdlet of the pipeline, i.e. a single source. You could, for example, execute this…

to emit the name of all processes with the prefix “win”. Without the parentheses, the argument passed as the -name parameter is “win*.name”, which is quite different!

An important aspect of a grouping expression is the encapsulation. The content of the expression is executed until completion and the result is then returned to be operated on by something else. Taking advantage of this encapsulation is what allows you to update a file in-place (i.e. without a temporary file or file renaming):

(Note that the percent (%) above is just a terse alias for ForEach-Object, PowerShell’s looping construct.) Without the parentheses, the content of myStuff.txt is fed a bit at a time through the pipeline by Get-Content so that Set-Content attempts to write to the same file that is in the midst of reading, so Set-Content fails.

$(...)

Similar to a grouping expression, this denotes a sub-expression. A sub-expression may encapsulate multiple commands or command sequences, separated by semicolons. Each sequence contributes to the output of the sub-expression.

In practice, though, sub-expressions are most useful inside a string literal; you rarely need them otherwise.  Inside a double-quoted string, you can interpolate simple variables simply by naming them, e.g.

But for interpolating the property of an object, you must wrap it in a sub-expression:

@(...)

With the at-sign, you have an array expression. Essentially the same as a sub-expression, except this guarantees to return an array. That little difference makes this notation very useful and very commonly used. Consider a cmdlet that returns a collection of a certain type, say X. If two or more objects are returned in a given call, they are returned as an array of type X.

If, on the other hand, only one object is being returned, you just get that object, an X. Wrapping the call in an array expression forces it to always be an array so you do not have to worry about edge cases for one value or no values, e.g.

Statements

Statements work together with expressions to provide the backbone components of PowerShell. Generally, a statement specifies an action to be performed without necessarily returning a value, whereas an expression performs some action that is designed to return a value. Interestingly, it is hard to say which is a “larger” component: expressions can be components of statements, and statements can be components of expressions.

There are several key symbols related to statements. As in many programming languages, you can group statements into a block to be treated as if it were a single statement. Use braces for this, i.e. { and }.

A statement terminates typically at the end of a line-where you have a line break-but if you want to put multiple statements on one line, you can use the other statement terminator, a semicolon (;). Alternatively, if you want to split a single statement across multiple lines you can do that with a line break as well-but only at places in the statement where PowerShell knows there is more to come. At other points, you have to explicitly tell PowerShell that there is more by using a backtick, or grave accent (`) as the very last character on a line. (A backtick is PowerShell’s escape character, so what you are doing is escaping the normal meaning of the immediately following line break.)

If, on the other hand, you want to chain statements together (i.e. if the output of one statement is supposed to be the input of the next statement), then use the pipe (|) symbol.

Comments

Comments in PowerShell, as in many languages, come in two flavors. Run-until-end-of-line comments begin with an octothorp (#), while block comments that span multiple lines are bracketed with <# and #>.

Variables

Variables are very simple in PowerShell-except for the complicating, little details. The first simple rule: all variables begin with a dollar sign ($). And the first exception: except when you want to use a hash table or an array to splat parameters to a function or cmdlet, then your variable starts with an at-sign. (Splatting is a technique for passing a dynamic list of parameters to a function; see about_Splatting.)

A basic variable may contain only letters, numbers, underscores, and question marks. (Note that letter and number are in the context of several specific Unicode character classes (Lu, Ll, Lt, Lm, Lo, or Nd), so there are many more characters permitted beyond the 36 standard English ones-18,571 more to be precise!) However, sometimes that’s just not enough. What if you really want a space in your variable name, or a virgule, or a colon, or… well, you get the idea. Perhaps the PowerShell team had some spare time to just “doodle” with the code base, but they did add support for this. Just enclose your variable name in braces and precede the whole thing, as usual, with a dollar sign. ${So this is a valid variable name!}

This notation is overloaded in a sense (or special-cased, if you prefer) in one very specific scenario. If the “name” you specify is a valid drive-qualified path (see Provider Paths) then you can not only retrieve that item but also store into that item as if it were a variable! An example makes this clear. The table shows conventional syntax on the left, which is exactly equivalent to the variable syntax on the right:

 

Conventional Notation

Variable Notation

Retrieve

$myData = Get-Content C:tmp.txt

$myData = ${C:tmp.txt}

Store

1,2,3 | Set-Content C:tmp.txt

${C:tmp.txt} = 1,2,3

Further you can apply addition (really appending) and multiplication (really replicating) to these variables as well! Here’s a neat example from the PowerShell 3.0 spec itself:

As soon as you go beyond simple scripts, you’ll need to be aware of scope in PowerShell. Variables are by default defined in local scope, meaning they exist only within the confines of the current function or script. But you have several named scopes you may specify (global, private, and script are likely the most common ones you will need). You specify a scoped variable by saying $scope:name as in, for example, $global:myStuff.

When a variable contains an object-something beyond a simple value like an integer or a string-you naturally need to be able to refer to components of that object. Use a period to dereference, as in $process.Name. That notation even works for hash tables, where instead of a property you specify a key, e.g. $myColorHash.blue. Again, though PowerShell is flexible. You can also reference hash items with brackets, so $myColorHash["blue"] would return the same value. Finally, arrays use this same bracketed notation, but of course the indexer must be an expression that evaluates to a number.

Quotes

Use quotation marks (single or double) to surround string literals in PowerShell, just as you do in many other languages. I would like to say that quoting is so simple in PowerShell that hardly anything needs to be said… but that’s not quite the case. In fact, I wrote a whole article about the nitty-gritty details about quoting (see When to Quote in PowerShell): But in a nutshell, use double quotes if you want variables and expressions to be interpolated within your literal, and use single quotes if you do not. That applies to both regular strings ("..." and '...') and here strings (@'...'@ and @"..."@ ), the latter typically used for multi-line strings.

Redirects

PowerShell takes file redirects to the “nth” degree (see about_Redirection). If you’ve used DOS shell, you have likely seen a simple file redirect, e.g. dostuff.exe > myfile.log to overwrite a file or dostuff.exe >> myfile.log to append to a file. With Unix/Linux you’ve likely seen that as well as the bit more convoluted which merges your standard error stream with your standard output stream. PowerShell has those and more, because there are five streams: standard, error, warning, verbose, and debug output streams. You can redirect any of them to a file by number Get-Stuff 4> myfile.log or Get-Stuff 4>> myfile.log, or you can merge any of them with the standard output:. PowerShell does not, however, have input redirection with a less than (<).

Arithmetic and Assignment

PowerShell has a typical complement of the four basic arithmetic operators ( +, -, *, and / )plus a modulus operator (%). What is particularly handy is that PowerShell also provides compound assignment for all of those ( +=, -=, *=, /=, and %= ). That is, a += 5 is the compound assignment analogous to the a = a + 5 simple assignment. PowerShell also provides the very typical auto-increment (++) and auto-decrement (--).

Summary

All of the above was just to add a bit of color to the information-dense wallchart just ahead. Give it a click and you’ll see how every punctuation mark on your keyboard is used (and reused!) in PowerShell. (Well, except for one-see if you can spot it!)

2289-imgC7.jpg

Afterthought

2289-psCartoon.jpg