Do curly braces mean anything in PowerShell variable declaration? - powershell

I have come across variables (or parameters) being declared like this:
${var_name} = "Hello world!"
As far as I can tell, this is no different to the following:
$var_name = "Hello world!"
I am wondering if the {} braces in the first example do or mean anything. Do they change the behaviour of the variable?

Curly braces in PowerShell variable names allow for arbitrary characters in the name of the variable. If there are no "pathological" characters in the variable name, then the braces are not needed and have no effect.
You'll find that "generated" code will sometimes use curly braces because they guarantee that the variable name is valid.

the {} braces use for declare variables with spaces in the middle or inside of the variable, like this:
${var_name hello } = "Hello world!2"
$var_name = "Hello world!"
it's not the same, 'cause you can't save data in a variable with spaces, powershell understand the variable until a space, except it's inside the braces.
Have a good day. (:

What might not be obvious on a first glance is that you can use any provider within ${}, for example:
${c:\tmp\foo.txt}="Hello World" # C: uses file system provider
The effect depends on the provider. For the file system provider the example changes the content of the specified file.

Related

PowerShell string format different behaviour within function

While using powershell I struggle to build up a filename from two variables. When I originally creaded the powershell script, it was working fine. Now I have tried to move some repeatable steps into a function, but the string behaviour is different.
MWE:
$topa = "ABC"
$topb = "XYZ"
function Test-Fun{
param(
$a,
$b
)
echo "$($a)H$($b).csv"
}
echo "$($topa)H$($topb).csv"
Test-Fun($topa, $topb)
The output on my system is
ABCHXYZ.csv
ABC XYZH.csv
Originally, I wanted to use an underscore instead of H and thought that is causing issues, but its not. What did I miss or rather what is the difference between string expansion within a function and outside of it?
You are calling Test-Func wrong. The comma after $topa will create an array, so you basically pass []"ABC", "XYZ" as an array to $a. In that case $b is empty!
You can easily fix this by removing the comma (also the parentheses are not necessary):
Test-Fun $topa $topb

implicit __source__ argument to julia macro can't be used within quote block

I'll start with my code:
macro example(args...)
local s = __source__
println(s) # This part works, showing macro is called on line 9
quote
println(s) # Julia tells me this variable "s" is not defined
println(__source__) # Likewise, "__source__" is not defined here either
end
end
#example 42 # Line 9 of my file
In my macro above I want to record the line number that is calling the macro and use it within my quote block. Both capturing it in a variable outside the quote block and using it within, or using it directly in the quote block don't work. My understanding is the code outside the quote block runs at parse-time, and the expression returned from the quote block is evaluated at run-time.
I feel like there must be a way to capture that variable and inject it right into the expression that will be evaluated later, but I haven't figured out how to do that. Any help here is appreciated. If there is a better way to do this let me know.
I ended up finding out an answer on my own. In the second line if I changed __source__ to __source__.line or __source__.file it worked fine as long as I then used $ to interpolate the result into the expression the macro returned. I'm still not sure why __source__ on its own didn't work, but using either .line or .file methods is working for me now.
I'm experiencing a similar problem trying to use __source__.
I think I can offer insight into why source.line, etc worked though.
The value of source.line is an integer. The value of source.fike is a string. Numbers and strings evaluate to themselves.
A symbol, on the other hand, evaluates to whatever value it has in the environment.

Powershell function reference and naming conventions

I recently discovered that you can get powershell's functions by reference using the modifier $function:. But I noticed a strange problem...
By convention, POSH uses a {Verb}-{Noun} convention for function names, where {Verb} is part of aproved POSH verb names. For instance: Get-Member or Invoke-WebRequest.
The thing is, that calling $function:Get-Member, for example, is not valid because of the hyphen; it works just fine if you declare a function like ShowMessage and calls: $fn = $function:ShowMessage. So I'd like to know if there's a way to escape this call.
PS.: I do know of another option, but is much much more verbose:
function Show-Message { Write-Host "Foo"; }
$fn = (Get-Item "function:Show-Message").ScriptBlock;
$fn.Invoke();
Update: Although #PetSerAl was very helpfull and explained the problem, I'll mark #Ansgar Wiechers's response as the answer because it's better documented.
function: is a PSDrive, not a (scope)modifier. As for using it with variable-like notation ($function:name): the rules for variable names with special characters apply here as well.
From the documentation:
VARIABLE NAMES THAT INCLUDE SPECIAL CHARACTERS
Variable names begin with a dollar sign. They can include alphanumeric characters and special characters. The length of the variable name is limited only by available memory.
Whenever possible, variable names should include only alphanumeric characters and the underscore character (_).Variable names that include spaces and other special characters, are difficult to use and should be avoided.
To create or display a variable name that includes spaces or special characters, enclose the variable name in braces. This directs PowerShell to interpret the characters in the variable name literally.
Your notation should thus look like this:
${function:Show-Message}
It can be invoked like this:
& ${function:Show-Message}

What is the meaning of ${} in powershell?

I have a script where function parameters are expressed like this:
param(
${param1},
${param2},
${param3}
)
What does it mean? I have been unable to find documentation on this.
What's the point of writing parameters that way instead of the more usual
param(
$param1,
$param2,
$param3
)
?
#MikeZ's answer is quite correct in explaining the example in the question, but as far as addressing the question title, there is actually more to say! The ${} notation actually has two uses; the second one is a hidden gem of PowerShell:
That is, you can use this bracket notation to do file I/O operations if you provide a drive-qualified path, as defined in the MSDN page Provider Paths.
(The above image comes from the Complete Guide to PowerShell Punctuation, a one-page wallchart freely available for download, attached to my recent article at Simple-Talk.com.)
They are both just parameter declarations. The two snippets are equivalent. Either syntax can be used here, however the braced form allows characters that would not otherwise be legal in variable names. From the PowerShell 3.0 language specification:
There are two ways of writing a variable name: A braced variable name, which begins with $, followed by a curly bracket-delimited set of one or more almost-arbitrary characters; and an ordinary variable name, which also begins with $, followed by a set of one or more characters from a more restrictive set than a braced variable name allows. Every ordinary variable name can be expressed using a corresponding braced variable name.
From about_Variables
To create or display a variable name that includes spaces or special characters, enclose the variable name in braces. This directs Windows PowerShell to interpret the characters in the variable name literally.
For example, the following command creates and then displays a variable named "save-items".
C:\PS> ${save-items} = "a", "b", "c"
C:\PS> ${save-items}
a
b
c
They are equivalent. It's just an alternative way of declaring a variable.
If you have characters that are illegal in a normal variable, you'd use the braces (think of it as "escaping" the variablename).
There is one additional usage.
One may have variable names like var1, var2, var11, var12, var101, etc.
Regardless if this is desirable variable naming, it just may be.
Using brackets one can precisely determine what is to be used:
assignment of $var11 may be ambiguous, using ${var1}1 or ${var11} leaves no room for mistakes.

Setting a Perl variable as an environment variable

I'm trying to set a variable I previously set in a Perl script as an environment variable, but it seems to not realize the parameter I'm passing in is a variable and not the actual path I want.
For example, when I run this:
$ENV{'ENV_VARIABLE'}='\'$file_path\'';
print($ENV{'ENV_VARIABLE'});
I only get:
'$file_path'
Is there any way I can tell it that what I'm passing in is actually a variable and not a literal string?
In Perl, single quoted strings do not interpolate variables. You want to use a double quote:
$ENV{'ENV_VARIABLE'}= "'$file_path'";
In that line, the rvalue is interpreted as q{'} . $file_path . q{'} where q{'} is a fancy way of writing '\'', which is a bit harder to read.