PowerShell Troubleshooting Guide
上QQ阅读APP看书,第一时间看更新

PowerShell strings

In PowerShell, either double quotes or single quotes can be used to express string literals. For instance, the following values are the same:

"HELLO WORLD"
'HELLO WORLD'

Using both kinds of quotes can be useful when quoting strings which themselves contain quotes, such as the following:

"I can't stop using PowerShell"
'He said, "I like using PowerShell" all day long'

If a single quote is needed in a single-quoted string, you can double the quote (for example, 'can't is a contraction'). The same technique allows the use of double-quotes in a double-quoted string. Strings written this way can be somewhat confusing to look at and it is easy to lose track of the number of quotes. A simpler method of including a double quote character in a string is to escape it with the backtick (`), also called a grave accent. The following string is an example: "the `" character is a double quote".

A peculiar kind of string in PowerShell is called a here-string. Here-strings allow strings to cross several lines and also to contain quotes of either kind without any doubling. Here-strings begin with either @" or @' at the end of a line and end with "@ or '@ respectively at the beginning of a line. A common error is to indent the closing punctuation (so that it is not at the beginning of a line) which causes the here-string to not be terminated. The syntax highlighting in the integrated scripting environment (ISE) will provide a good visual cue that something isn't quite right in this situation. The following illustration shows a couple of correctly formatted here-strings and one that isn't correctly terminated. Note that the text after the final here-string shows an error and the code hint explains the problem:

String substitution

The main difference between single- and double-quoted strings (both normal strings and here-strings) is that single-quoted strings are static while double-quoted strings perform string substitution. Variable references contained in double-quoted strings are replaced with string representations of the contents of the variable. For example, if the variable $name contains the value "Mike", the double-quoted string "My name is $name!" would become "My name is Mike!".

String substitution is a great timesaver. In many languages, embedding values in string output involves string concatenation, and code ends up with lots of expressions such as "My name is "+$name+"!". If the desired output involves several variables, the expression will need to be broken down into more and more segments. However, embedding several variables in PowerShell is often as simple as including the variable names in the string.

For simple objects (such as strings, integers, and floating point numbers), the representation of the variable that is used in the string substitution is the same value that you would see if you used Write-Host (for example) to display the value. For complex objects, however, the value is the result of the object's ToString() method. This means, generally, the way $var is output is different from how "$var" is output, as shown in the following screenshot:

If a variable is an array, the value that is placed in a string is the value of each of the items in the array separated by the value of the built-in $ofs variable (which stands for output field separator). The default value of $ofs is a space, but it can be changed to create strings delimited by whatever is desired, as shown in the following screenshot:

How string substitution goes wrong

String substitution is a simple concept, but there are a few common issues that people encounter with it. First, it is critical to realize that string substitution is only performed on double-quoted strings. For example, the string 'My name is $name!' will not be changed in any way. A second common error is trying to embed something more complicated than a variable value in a string. For instance, if $file is a reference to a file, you might be tempted to use "the file is $file.length bytes long" and expect to have the length of the file replace $file.length in the string. The rule of string substitutions that the engine looks for a variable name and replaces it with a value. In this case, $file is the name of a variable and it will be replaced with the name of the file. The remainder of the string will be unchanged, as shown in the following code snippet:

$file=dir *.* | select -first 1

"the file is $file.length bytes long"
the file is C:\Users\Mike\.gradle.length bytes long

In order to include complicated expressions in a string, one approach is to use the subexpression operator $(); for example, "the file is $($file.length) bytes long". Subexpressions in strings are not limited to property references, though. Any expression (including cmdlets) is allowed. The string "the process started at $(Get-Date)" is an example of using code in a string.

A second method to include complicated expressions in a string is to use the format operator, -f. Using the format operator involves preparing a string with placeholders numbered starting with zero and providing a list of values to be substituted. The previous example involving file lengths could be rewritten using the format operator as follows:

"the file is {0} bytes long" -f $file.length

Including more than one value is just as easy:

"the file {0} is {1} bytes long" -f $file.FullName,$file.length

There are several advantages to using the format operator over using string substitution. First, since the placeholders are short, the final string is much shorter in the code listing and will be easier to read on the screen and in a printout. Second, with the format operator, special formatting codes can be applied to the placeholders to format the values in specific ways. For example, formatting a date value in a long date format would use a placeholder such as {0:D}, and formatting a floating point value with two decimals would use {0:N2}. A reference for formatting codes can be found at http://msdn.microsoft.com/en-us/library/26etazsy.aspx.

Escaping in PowerShell strings

A common practice in programming languages is to use the backslash (\) as an escape character to allow special characters to be written in strings. PowerShell's integration as a scripting and command-line language necessitates that the backslash not be given any special meaning other than the traditional meaning as a path separator. Therefore, the backtick is used as the escape character. To include a dollar sign in a string without triggering substitution, you can escape the dollar sign with a backtick like so: "the value of the variable `$var is $var". Notice that the first dollar sign is escaped with a backtick but the second one isn't, so the second $var will be replaced. This technique was mentioned earlier to include a literal double quote in a double-quoted string. An important point to remember is that substitution is not performed on single-quoted strings, so including an escaped single quote in a single-quoted string doesn't work.

The following is a table of allowed special characters in double-quoted strings: