I would like to request some help with extracting out some characters that are returned from a Powershell query.
The query is:
$x = Get-Package -Provider "Programs" -Name "*SomeWindowsApplication*" | Select-Object -Property FastPackageReference | Out-String
The returned format is
FastPackageReference
---------------------
hklm32\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{80F3CCC1-BBAF-45DD}
I am trying to extract (to a variable) just the value returned within the { } curly brackets
When using
$x.TrimStart("hklm32")
or
$x.Trim("hklm32")
neither appear to make any change to the string.
I've tested that it is a string using $x.GetType()
The outcome I require is a variable eg: $appvalue which when queried returns the value eg: {80F3CCC1-BBAF-45DD} including the { } brackets.
Thanks, much appreciated for any assistance.
update: a colleague of mine suggested this code, which works but it assumes the GUID is always 38 characters. (might not be a problem for this application though)
$GUID=$x.substring($x.IndexOf("{"),38)
CodePudding user response:
First of all, you need to remove | Out-String
, because what you are after is the value inside property FastPackageReference
Try:
$x = Get-Package -Provider "Programs" -Name "*SomeWindowsApplication*" | Select-Object -Property FastPackageReference
$guid = ([regex]'(?i){([\dA-F-] )}$').Match($x.FastPackageReference).Groups[1].Value
or
# expand the property, so $x will only have the value, not an object with property FastPackageReference
$x = Get-Package -Provider "Programs" -Name "*SomeWindowsApplication*" | Select-Object -ExpandProperty FastPackageReference
$guid = ([regex]'(?i){([\dA-F-] )}$').Match($x).Groups[1].Value
Variable $guid
now has value 80F3CCC1-BBAF-45DD
Regex details:
{ Match the character “{” literally
( Match the regular expression below and capture its match into backreference number 1
[\dA-F-] Match a single character present in the list below
A single digit 0..9
A character in the range between “A” and “F”
The character “-”
Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
} Match the character “}” literally
$ Assert position at the end of a line (at the end of the string or before a line break character)
The (?i)
makes the regex work case-insensitively
CodePudding user response:
Let me complement Theo's helpful answer, which shows advanced regex techniques, with simpler alternatives, if the following assumption can be made:
Given that it looks like the substring of interest is the last \
-separated token, an alternative to using a regex is to treat the string as a path and extract its leaf (file-name) component via Split-Path
:
# Get the property value(s) of interest.
$x = (Get-Package -Provider Programs -Name *SomeWindowsApplication*).FastPackageReference
# -> '{80F3CCC1-BBAF-45DD}', with your sample data
Split-Path -Leaf $x
A more concise regex-solution is possible too, using a -replace
operation:
$x -replace '^[^{] '
The regex matches from the start of the input string (^
) one or more characters (
) that are not {
([^{]
), i.e. everything up to but not including {
; by not specifying a replacement string, the matched part is replaced with the empty string i.e. effectively removed, leaving only the {...}
part at the end.