Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell String Formatting: Why is the colon character causing my variable's value to be blank?

Tags:

powershell

I was looking over what's coming with the next WinRM and PowerShell 3 and I was looking through the list of breaking changes and saw something that I'd never seen before.

The example was:

$server = "msp42" $status = "online" "$server: $status" 

The resulting output was:

online

OK, I'd never encountered that before and have no clue why the colon caused an issue. A solution suggested in the document was to put a space (which is silly because then you change the output):

"$server : $status" 

Another suggestion was to use this format (new to me!):

"${server}: $status" 

The final suggestion was to make an expression, which I am familiar with and use all the time:

"$($server): $status" 

So, my questions to you PowerShell gurus out there are:

  1. What the heck is up with that colon? Does it do something?

  2. What the heck is the ${variable} syntax? Is it strictly to deal with the colon or does it have some neat features?

like image 830
Kevin Buchan Avatar asked Dec 05 '11 13:12

Kevin Buchan


People also ask

What does double colon mean in PowerShell?

This is a question for Windows PowerShell in Action. The :: operator is the static member accessor. Whereas the dot operator retrieved instance members, the double-colon operator accesses static members on a class, as is the case with the join method in the example at the end of the last section.

How do I format a string in PowerShell?

To format a string in a PowerShell we can use various methods. First using the simple expanding string method. PS C:\> $str = 'PowerShell' PS C:\> Write-Output "Hello $str !!!!" Hello PowerShell !!!! Second, using the format method.

What is @' in PowerShell?

@' The $profile variable contains the path of your PowerShell profile. '@ The output of this command is: Output Copy. The $profile variable contains the path of your PowerShell profile. In double-quoted here-strings, variables are replaced by their values.

How do you use a colon in PowerShell?

The answer is that the colon has a special meaning in PowerShell variable names: It's used to associate the variable with a specific scope or namespace. There are a few scopes defined by PowerShell, such as script and global; so for example a global variable might be named $global:var.


2 Answers

The colon is a valid character for variable names, e.g. in $Env:PATH, etc.

You can use the following option, too

$server`: $status 

or, for some cases a format string is more readable:

'{0}: {1}' -f $server, $status 

Back to the colon. There is a special case for variable names that correspond to an item on a PSDrive:

$Env:Foo           # equivalent to the contents of Env:\Foo $Function:C:       # equivalent to the contents of Function:\C: ${C:\autoexec.bat} # ... you get the picture 

The syntax ${} exists to be able to specify variable names that otherwise use characters reserved for other parts of the syntax. You could see it as being similar (but more powerful) to C#'s @ in front of identifiers. See above where a \ is used in the variable name, since $Drive:Item only works for the current container on a drive (or the root for non-hierarchic ones like Env, Alias or Function).

Another example where the variable name would be normally invalid syntax:

PS> $+ The term '$+' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:1 + $+ + ~~     + CategoryInfo          : ObjectNotFound: ($+:String) [], CommandNotFoundException     + FullyQualifiedErrorId : CommandNotFoundException  PS> ${+} = 5 PS> ${+} 5 PS> Get-Variable +  Name                           Value ----                           ----- +                              5 
like image 92
Joey Avatar answered Sep 19 '22 22:09

Joey


Attribution:
The following answer was copied from Tomas Restrepo's blog at https://winterdom.com/2008/02/20/watchoutforinpowershell

Here's something that tripped me the other day in a Windows PowerShell script. Let's say that you have to variables $user and $machine, and want to print a string with the value of both of them separated by a colon (':').

You can obviously do it using string concatenation:

$user = 'tomasr'  $machine = 'arcano'   write ($user + ':' + $machine) 

That works, but doesn't PowerShell support that nice string interpolation feature? Why, yes it does! So why don't we just rewrite it like this:

write "$user:$machine" 

But wait! If you run that last line, all you get is the value of the $machine variable... where did $user go?

The answer is that the colon has a special meaning in PowerShell variable names: It's used to associate the variable with a specific scope or namespace. There are a few scopes defined by PowerShell, such as script and global; so for example a global variable might be named $global:var.

But haven't we also seen that syntax elsewhere? Sure, how about $env:PATH? Same thing; except here env isn't a scope by itself, but a PSDrive. So the part before the ':' can either be either an actual scope defined by PS or a PSDrive. Heck, you can even try something like "${c:autoexec.bat}" and watch the magic happen!

So the problem with our string interpolation is that when PowerShell sees "$user:$machine", it expects to find a scope/psdrive named 'user' and expects a variable name to follow the ':', but '$' isn't valid, and 'user' isn't a scope or a PSDrive either, which confuses PowerShell a bit. But since he's too much of a gentleman he just fixes it up as best as he can and ignores everything up to this point and just dumps $machine without complaining. Nice of him, but it can really trip you up if you don't expect it!

Can we avoid this? Yes, we can, by simply delimiting variable names exactly for PowerShell by using '{}', like this:

write "${user}:$machine" 

Section 5.8 on page 141 of Bruce Payette's excellent Windows PowerShell in Action covers the topic of variables in PowerShell and gave me the clue to work around this issue.

like image 43
Vinay Avatar answered Sep 18 '22 22:09

Vinay