Uninstall Package with PowerShell not working using Variable [duplicate] - powershell

I have a string that I want to insert dynamically a variable. Ex;
$tag = '{"number" = "5", "application" = "test","color" = "blue", "class" = "Java"}'
I want to accomplish:
$mynumber= 2
$tag = '{"number" = "$($mynumber)", "application" = "test","color" = "blue", "class" = "Java"}'
What I want is to have the variable inserted on the string, But it is not going through. I guess the '' sets all as a string. Any recomendations on how should I approach this?
thanks!
powershell test and trial and error. Also Google.

The reason your current attempt doesn't work is that single-quoted (') string literals in PowerShell are verbatim strings - no attempt will be made at expanding subexpression pipelines or variable expressions.
If you want an expandable string literal without having to escape all the double-quotes (") contained in the string itself, use a here-string:
$mynumber = 2
$tag = #"
{"number" = "$($mynumber)", "application" = "test","color" = "blue", "class" = "Java"}
"#

To add to Mathias' helpful answer:
Mistakenly expecting string interpolation inside '...' strings (as opposed to inside "...") has come up many times before, and questions such as yours are often closed as a duplicate of this post.
However, your question is worth answering separately, because:
Your use case introduces a follow-up problem, namely that embedded " characters cannot be used as-is inside "...".
More generally, the linked post is in the context of argument-passing, where additional rules apply.
Note: Some links below are to the relevant sections of the conceptual about_Quoting_Rules help topic.
In PowerShell:
only "..." strings (double-quoted, called expandable strings) perform string interpolation, i.e. expansion of variable values (e.g. "... $var" and subexpressions (e.g., "... $($var.Prop)")
not '...' strings (single-quoted, called verbatim strings), whose values are used verbatim (literally).
With "...", if the string value itself contains " chars.:
either escape them as `" or ""
E.g., with `"; note that while use of $(...), the subexpression operator never hurts (e.g. $($mynumber)), it isn't necessary with stand-alone variable references such as $mynumber:
$mynumber= 2
$tag = "{`"number`" = `"$mynumber`", `"application`" = `"test`",`"color`" = `"blue`", `"class`" = `"Java`"}"
Similarly, if you want to selectively suppress string interpolation, escape $ as `$
# Note the ` before the first $mynumber.
# -> '$mynumber = 2'
$mynumber = 2; "`$mynumber` = $mynumber"
See the conceptual about_Special_Characters help topic for info on escaping and escape sequences.
If you need to embed ' inside '...', use '', or use a (single-quoted) here-string (see next).
or use a double-quoted here-string instead (#"<newline>...<newline>"#):
See Mathias' answer, but generally note the strict, multiline syntax of here-strings:
Nothing (except whitespace) must follow the opening delimiter on the same line (#" / #')
The closing delimiter ("# / '#) must be at the very start of the line - not even whitespace may come before it.
Related answers:
Overview of PowerShell's expandable strings
Overview of all forms of string literals in PowerShell
When passing strings as command arguments, they are situationally implicitly treated like expandable strings (i.e. as if they were "..."-enclosed); e.g.
Write-Output $HOME\projects - see this answer.
Alternatives to string interpolation:
Situationally, other approaches to constructing a string dynamically can be useful:
Use a (verbatim) template string with placeholders, with -f, the format operator:
$mynumber= 2
# {0} is the placeholder for the first RHS operand ({1} for the 2nd, ...)
'"number" = "{0}", ...' -f $mynumber # -> "number" = "2", ...
Use simple string concatenation with the + operator:
$mynumber= 2
'"number" = "' + $mynumber + '", ...' # -> "number" = "2", ...

Related

Array not recognized by powershell parser when other operators are involved

Assigning an array looks like this:
PS> $x = "a", "b"
PS> $x
a
b
Now, i wanted to add a 'root string' ("r") to any element so I did this (actually i used a variable, but for the sakeness of simplicity let's just use a string here):
PS> $x = "r" + "a" , "r" + "b"
PS> $x
ra rb
Looking at the output, I didn't get the array that I expected, but a single string with a "space" (I checked: it's a 32 ascii char, so a space, not a tab or another character).
That is: the comma seems to be interpreted as a string join operator, which I couldn't find any reference to.
Even worst, I get the feeling of not understanding how the parser works here. I had a look at about_Parsing; what I found seems not to apply to this case.
Commas (,) introduce lists passed as arrays, except when the command
to be called is a native application, in which case they are
interpreted as part of the expandable string. Initial, consecutive or
trailing commas are not supported.
The first obvious fix that I came up with is the following:
PS> $x = ("r" + "a") , ("r" + "b")
PS> $x
ra
rb
Maybe there are others, and I am expecially intrested in the ones that reveal how the parser actually works. What I would like to fix the most is my knowledge of the parsing rules.
To flesh out the helpful comments on the answer:
tl;dr
Due to operator precedence, your command is parsed as "r" + ("a" , "r") + "b", causing array "a", "r" to be implicitly stringified to verbatim a r, resulting in two string concatenation operations yielding a single string with verbatim content ra rb.
Using (...) is indeed the correct way to override operator precedence.
"r" + "a" , "r" + "b"
is an expression involving operators.
Expressions are parsed in expression mode, which contrasts with argument mode; the latter applies to commands, i.e. named units of functionality that are called with shell-typical syntax (whitespace-separated arguments, quotes around simple strings optional). Arguments (parameter values) in argument mode are parsed differently from operands in expression mode, as explained in the conceptual about_Parsing help topic. Your quote about , relates to argument mode, not expression mode.
The conceptual about_Operator_Precedence help topic describes the relative precedence among operators, from which you can glean that ,, the array constructor operator has higher precedence than the + operator
Therefore, your expression is parsed as follows (using (...), the grouping operator, to make the implicit rules explicit):
"r" + ("a" , "r") + "b"
+ is polymorphic in PowerShell, and with a [string] instance as the LHS the RHS is coerced to a string too.
Therefore, array "a" , "r" is stringified, which uses PowerShell's custom array stringification, namely joining the (potentially stringified) array elements with a space.[1]
That is, the array stringifies to a string with verbatim content a r.
As an aside: The same stringification is applied in the context of string interpolation via expandable (double-quoted) strings ("..."); that is, "$("a", "r")" also yields verbatim a r
Therefore, the above is equivalent to:
"r" + "a r" + "b"
which yields verbatim ra rb.
(...) is indeed the appropriate way to ensure the desired precedence:
("r" + "a"), ("r" + "b") # -> array 'ra', 'rb'
[1] Space is the default separator character. Technically, you can override it via the $OFS preference variable, though that is rarely used in practice.
Another way to do it. The type of the first term controls what type of operation the plus performs. The first term here is an empty array. If you want the plus to do both kinds of operations, there's no getting around extra parentheses to change the operator precedence.
#() + 'ra' + 'rb'
ra
rb
Or more commonly:
'ra','rb' + 'rc'
ra
rb
rc

Powershell Formatting for a String

I have a string that I want to insert dynamically a variable. Ex;
$tag = '{"number" = "5", "application" = "test","color" = "blue", "class" = "Java"}'
I want to accomplish:
$mynumber= 2
$tag = '{"number" = "$($mynumber)", "application" = "test","color" = "blue", "class" = "Java"}'
What I want is to have the variable inserted on the string, But it is not going through. I guess the '' sets all as a string. Any recomendations on how should I approach this?
thanks!
powershell test and trial and error. Also Google.
The reason your current attempt doesn't work is that single-quoted (') string literals in PowerShell are verbatim strings - no attempt will be made at expanding subexpression pipelines or variable expressions.
If you want an expandable string literal without having to escape all the double-quotes (") contained in the string itself, use a here-string:
$mynumber = 2
$tag = #"
{"number" = "$($mynumber)", "application" = "test","color" = "blue", "class" = "Java"}
"#
To add to Mathias' helpful answer:
Mistakenly expecting string interpolation inside '...' strings (as opposed to inside "...") has come up many times before, and questions such as yours are often closed as a duplicate of this post.
However, your question is worth answering separately, because:
Your use case introduces a follow-up problem, namely that embedded " characters cannot be used as-is inside "...".
More generally, the linked post is in the context of argument-passing, where additional rules apply.
Note: Some links below are to the relevant sections of the conceptual about_Quoting_Rules help topic.
In PowerShell:
only "..." strings (double-quoted, called expandable strings) perform string interpolation, i.e. expansion of variable values (e.g. "... $var" and subexpressions (e.g., "... $($var.Prop)")
not '...' strings (single-quoted, called verbatim strings), whose values are used verbatim (literally).
With "...", if the string value itself contains " chars.:
either escape them as `" or ""
E.g., with `"; note that while use of $(...), the subexpression operator never hurts (e.g. $($mynumber)), it isn't necessary with stand-alone variable references such as $mynumber:
$mynumber= 2
$tag = "{`"number`" = `"$mynumber`", `"application`" = `"test`",`"color`" = `"blue`", `"class`" = `"Java`"}"
Similarly, if you want to selectively suppress string interpolation, escape $ as `$
# Note the ` before the first $mynumber.
# -> '$mynumber = 2'
$mynumber = 2; "`$mynumber` = $mynumber"
See the conceptual about_Special_Characters help topic for info on escaping and escape sequences.
If you need to embed ' inside '...', use '', or use a (single-quoted) here-string (see next).
or use a double-quoted here-string instead (#"<newline>...<newline>"#):
See Mathias' answer, but generally note the strict, multiline syntax of here-strings:
Nothing (except whitespace) must follow the opening delimiter on the same line (#" / #')
The closing delimiter ("# / '#) must be at the very start of the line - not even whitespace may come before it.
Related answers:
Overview of PowerShell's expandable strings
Overview of all forms of string literals in PowerShell
When passing strings as command arguments, they are situationally implicitly treated like expandable strings (i.e. as if they were "..."-enclosed); e.g.
Write-Output $HOME\projects - see this answer.
Alternatives to string interpolation:
Situationally, other approaches to constructing a string dynamically can be useful:
Use a (verbatim) template string with placeholders, with -f, the format operator:
$mynumber= 2
# {0} is the placeholder for the first RHS operand ({1} for the 2nd, ...)
'"number" = "{0}", ...' -f $mynumber # -> "number" = "2", ...
Use simple string concatenation with the + operator:
$mynumber= 2
'"number" = "' + $mynumber + '", ...' # -> "number" = "2", ...

unexpected token in in expression or statement

I want to save a string with a skeletton and a few variables in there to use it later.
My string:
$moddeduserdata = ("{"Id":$userid,"Timestamp":"$timestamp","FirstName":"$numberout","LastName":"$numberout","CallId":"$numberout"}")
What I want is the following output:
{"Id":261,"Timestamp":"AAAAAAAJ1KM=","FirstName":"5503","LastName":"5503","CallId": "5503"}
so this results in the error:
"unexpected token"
I also tried with ' ' instead of " " but then it just saves the line without putting in my variables.
You're trying to embed verbatim " characters in a double-quoted string ("..."), so you must escape them as `" ("" works too):
$moddeduserdata = "{`"Id`":$userid,`"Timestamp`":`"$timestamp`",`"FirstName`":`"$numberout`",`"LastName`":`"$numberout`",`"CallId`":`"$numberout`"}"
While single-quoted strings ('...') allow you to embed " chars. as-is (no need for escaping), they do not perform the string interpolation (expansion of embedded variable references) you need.
For more information about PowerShell string literals, see the bottom section of this answer.
Or make an object then convert it to compressed json:
$userid,$timestamp,$numberout,$numberout,$numberout = echo 261 AAAAAAAJ1KM 5503 5503 5503
[pscustomobject]#{Id=$userid;Timestamp=$timestamp;FirstName=$numberout;
LastName=$numberout;CallId=$numberout} | convertto-json -compress
{"Id":261,"Timestamp":"AAAAAAAJ1KM=","FirstName":"5503","LastName":"5503","CallId":"5503"}

Pass string value having space to another powershell file

I have a powershell script which calls another powershell file passing a string argument.
param (
[string]$strVal = "Hello World"
)
$params = #{
message = "$strVal"
}
$sb = [scriptblock]::create(".{$(get-content $ps1file -Raw)} $(&{$args} #params)")
Somehow the script passes message variable without double quotes so the powershell file receives only the first part of the message variable (before space) i.e. "Hello".
How can I pass the strVal variable with space (i.e. "Hello World")?
A double quote pair signals PowerShell to perform string expansion. If you want double quotes to output literally, you need to escape them (prevent expansion) or surround them with single quotes. However, a single quote pair signals PowerShell to treat everything inside literally so your variables will not interpolate. Given the situation, you want string expansion, variable interpolation, and literal double quotes.
You can do the following:
# Double Double Quote Escape
#{message = """$strVal"""}
Name Value
---- -----
message "Hello World"
# Backtick Escape
#{message = "`"$strVal`""}
Name Value
---- -----
message "Hello World"
Quote resolution works from left to right, which means the leftmost quote type takes precedence. So '"$strVal"' will just print everything literally due to the outside single quote pair. "'$strVal'" will print single quotes and the value of $strVal.

String.Trim() not removing characters in a string

I need to create a String from double the use String.Trim() to remove the full stop, but it doesn't remove it. I think there is also a way to do this numerically but I'd like to do it with the string. Is there a reason it won't remove it? The output from the code is 5.5
$MyDouble = 5.5
[String]$MyDouble2 = $MyDouble
$MyDouble2.Trim(".")
$MyDouble2
String.Trim() only trims from the beginning and end of strings, so it has no effect in your command, because the . only occurs inside your input string.
If you truly want to remove just the . and keep the post-decimal-point digits, use the -replace operator:
$MyDouble2 -replace '\.' # -> '55'
Note:
* -replace takes a regex (regular expression) as the search operand, hence the need to escape regex metacharacter . as \.
* The above is short for $MyDouble2 -replace '\.', ''. Since the replacement string is the empty string in this case, it can be omitted.
If you only want to extract the integer portion, use either 4c74356b41's .Split()-based answer, or adapt the regex passed to -replace to match everything from the . through the end of the string.
$MyDouble2 -replace '\..*' # -> '5'
#Matt mentions the following alternatives:
For removing the . only: Using String.Replace() to perform literal substring replacement (note how . therefore does not need \-escaping, as it did with -replace, and that specifying the replacement string is mandatory):
$MyDouble2.Replace('.', '') # -> '55'
For removing the fractional part of the number (extracting the integer part only), using a numerical operation directly on $MyDouble (as opposed to via the string representation stored in $MyDouble2), via Math.Floor():
[math]::Floor($MyDouble) # -> 5 (still a [double])
Looking at some documentation for .Trim([char[]]) you will see that
Removes all leading and trailing occurrences of a set of characters specified in an array from the current String object.
That does not cover the middle of strings, so using the .Replace() method would accomplish that.
I think there is also a way to do this numerically but I'd like to do it with the string.
Just wanted to mention that converting numbers to strings to then drop decimals via string manipulation is a poor approach. Assuming your example is what you are actually trying to do, I suggest using a static method from the [math] class instead.
$MyDouble = 5.5
[math]::Floor($MyDouble)
$MyDouble = 5.5
[String]$MyDouble2 = $MyDouble
$MyDouble2.Replace(".", "")
Well, why would it trim not the last (or first) character? It wouldn't, what you need (probably) is:
$MyDouble = 5.5
[String]$MyDouble2 = $MyDouble
$MyDouble2.Split(".")[0]
$MyDouble = 5.5
[String]$MyDouble2 = $MyDouble
$res=$MyDouble2 -split "\."
$res[0..($res.Count-1)] -join ""