I'm trying to replace part of a string in Powershell. However, the replacement string is not hardcoded, it's calculated from a function:
$text = "the image is -12345-"
$text = $text -replace "-(\d*)-", 'This is the image: $1'
Write-Host $text
This gives me the correct result:
"This is the image: 12345"
Now, I want to include the base64 encoded image. I can read the image from the id. I was hoping the following would work, but it doesn't:
function Get-Base64($path)
{
[convert]::ToBase64String((get-content $path -encoding byte))
}
$text -replace "-(\d*)-", "This is the image: $(Get-Base64 '$1')"
The reason that it doesn't work, is because it first passes $1 (the string, not the value of $1) to the function, executes it and only then does it do the replace. What I want to do is
Find the occurrence of the pattern
Replace each occurence with the pattern
For each replace:
Pass the capture group to the function
Use the value of the capture group to get the base64 image
inject the base64 image into the replacement
You can use the static Replace method from the [regex] class:
[regex]::Replace($text,'-(\d*)-',{param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
Alternatively you can define a regex object and use the Replace method of that object:
$re = [regex]'-(\d*)-'
$re.Replace($text, {param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
For better readability you could define the callback function (the scriptblock) in a separate variable and use that in the replacement:
$callback = {
param($match)
'This is the image: ' + (Get-Base64 $match.Groups[1].Value)
}
$re = [regex]'-(\d*)-'
$re.Replace($text, $callback)
PetSerAl's helpful answer is your only option in Windows PowerShell, as of v5.1.
PowerShell Core v6.1+ now offers a native PowerShell solution via an enhancement to the
-replace operator, which obviates the need to call [regex]::Replace():
Just as with [regex]::Replace(), you can now:
pass a script block as the -replace replacement operand, which must return the replacement string,
except that the match at hand (an instance of type [System.Text.RegularExpressions.Match]) is represented as automatic variable $_, as is customary in PowerShell.
Applied to your case:
$text -replace "-(\d*)-", { "This is the image: $(Get-Base64 $_.Groups[1].Value)" }
A simpler example:
# Increment the number embedded in a string:
PS> '42 years old' -replace '\d+', { [int] $_.Value + 1 }
43 years old
Here's another way. Use the -match operator, and then reference $matches. Note that $matches doesn't get set with arrays on the left side of the -match operator. $matches.1 is the first grouping formed by the ( ).
$text = "the image is -12345-"
function Get-Base64($path) {
[convert]::ToBase64String( (get-content $path -asbytestream) ) } # ps 6 ver
if (! (test-path 12345)) { echo hi > 12345 }
$text -match '-(\d*)-'
$text -replace '-(\d*)-', "$(Get-Base64 $matches.1)"
the image is aGkNCg==
Or to break it up even more:
$text -match '-(\d*)-'
$result = Get-Base64 $matches.1
$text -replace '-(\d*)-', $result
Related
This question already has an answer here:
Reference - What does this regex mean?
(1 answer)
Closed 2 years ago.
So say you have a variable string like: "Report to Sam.Smith"
What's the best way for you to remove the words 'Report' and 'to' leaving only Sam.Smith using Powershell??
You have to use -replace :
$string = "Report to Sam.Smith"
$string = $string -replace "Report to ",""
$string # Output --> "Sam.Smith"
Or like this :
$string = "Report to Sam.Smith"
$string = $string.replace("Report to ","")
$string # Output --> "Sam.Smith"
But if you need to use Regex because the string's words can vary then you have to rethink the problem.
You won't be looking to erase a part of the string but to extract something out of it.
In you case, I think that you're looking for a username using a name.lastname format which is pretty easy to capture :
$string = "Report to Sam.Smith"
$string -match "\s(\w*\.\w*)"
$Matches[1] # Output --> Sam.Smith
Using -match will return True / False.
If it does return True, an array named $Matches will be created. It will contains on index 0 ($Matches[0]) the whole string that matched the regex.
Every others index greater than 0 will contains the captured text from the regex parenthesis called "capture group".
I would highly recommend using an if statement because if your regex return false, the array $Matches won't exist :
$string = "Report to Sam.Smith"
if($string -match "\s(\w*\.\w*)") {
$Matches[1] # Output --> Sam.Smith
}
I have to extract a string from square brackets using Powershell or Groovy script.
PowerShell :
$string = "[test][OB-110] this is some text"
$found = $string -match '(?<=\[)[^]]+(?=\])'
echo $matches
When I run the above code it returns :
test
I want it to return this :
test
OB-110
I need to extract all text within brackets.
-match will internally call Regex.Match() in the background, which in turn will only capture the first match.
Either use Select-String with the -AllMatches switch:
($string |Select-String '(?<=\[)[^]]+(?=\])' -AllMatches).Matches.Value
Or invoke Regex.Matches() directly:
[regex]::Matches($string, '(?<=\[)[^]]+(?=\])').Value
For Groovy:
def str = "[test][OB-110] this is some text"
str.findAll(/(?<=\[)[^]]+(?=\])/).each {
println it
}
Which prints
test
OB-110
I'm trying to replace part of a string in Powershell. However, the replacement string is not hardcoded, it's calculated from a function:
$text = "the image is -12345-"
$text = $text -replace "-(\d*)-", 'This is the image: $1'
Write-Host $text
This gives me the correct result:
"This is the image: 12345"
Now, I want to include the base64 encoded image. I can read the image from the id. I was hoping the following would work, but it doesn't:
function Get-Base64($path)
{
[convert]::ToBase64String((get-content $path -encoding byte))
}
$text -replace "-(\d*)-", "This is the image: $(Get-Base64 '$1')"
The reason that it doesn't work, is because it first passes $1 (the string, not the value of $1) to the function, executes it and only then does it do the replace. What I want to do is
Find the occurrence of the pattern
Replace each occurence with the pattern
For each replace:
Pass the capture group to the function
Use the value of the capture group to get the base64 image
inject the base64 image into the replacement
You can use the static Replace method from the [regex] class:
[regex]::Replace($text,'-(\d*)-',{param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
Alternatively you can define a regex object and use the Replace method of that object:
$re = [regex]'-(\d*)-'
$re.Replace($text, {param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
For better readability you could define the callback function (the scriptblock) in a separate variable and use that in the replacement:
$callback = {
param($match)
'This is the image: ' + (Get-Base64 $match.Groups[1].Value)
}
$re = [regex]'-(\d*)-'
$re.Replace($text, $callback)
PetSerAl's helpful answer is your only option in Windows PowerShell, as of v5.1.
PowerShell Core v6.1+ now offers a native PowerShell solution via an enhancement to the
-replace operator, which obviates the need to call [regex]::Replace():
Just as with [regex]::Replace(), you can now:
pass a script block as the -replace replacement operand, which must return the replacement string,
except that the match at hand (an instance of type [System.Text.RegularExpressions.Match]) is represented as automatic variable $_, as is customary in PowerShell.
Applied to your case:
$text -replace "-(\d*)-", { "This is the image: $(Get-Base64 $_.Groups[1].Value)" }
A simpler example:
# Increment the number embedded in a string:
PS> '42 years old' -replace '\d+', { [int] $_.Value + 1 }
43 years old
Here's another way. Use the -match operator, and then reference $matches. Note that $matches doesn't get set with arrays on the left side of the -match operator. $matches.1 is the first grouping formed by the ( ).
$text = "the image is -12345-"
function Get-Base64($path) {
[convert]::ToBase64String( (get-content $path -asbytestream) ) } # ps 6 ver
if (! (test-path 12345)) { echo hi > 12345 }
$text -match '-(\d*)-'
$text -replace '-(\d*)-', "$(Get-Base64 $matches.1)"
the image is aGkNCg==
Or to break it up even more:
$text -match '-(\d*)-'
$result = Get-Base64 $matches.1
$text -replace '-(\d*)-', $result
I have been trying to transform the following string:
CN=John Doe,OU=IT,OU=Support,OU=Department,OU=HQ,DC=FR,DC=CONTOSO,DC=COM
to:
FR.CONTOSO.COM
As a first step, I tried to remove everything until ",DC" pattern.
I thought I could use the un-greedy ".+?" to match everything until the first ",DC" pattern:
$str = 'CN=John Doe,OU=IT,OU=Support,OU=Department,OU=HQ,DC=FR,DC=CONTOSO,DC=COM'
$str -replace '.+?,DC', ''
This returns:
=COM
Any idea why it's getting only the last one even with the un-greedy version?
How could I do this?
Just split the string:
$parts = ('CN=John Doe,OU=IT,OU=Support,OU=Department,OU=HQ,DC=FR,DC=CONTOSO,DC=COM' -split ',')
$newString = '{0}.{1}.{2}' -f $parts[-3].split('=')[1], $parts[-2].split('=')[1], $parts[-1].split('=')[1]
OK, so I took #EBGreen's advice and decided to make a function that does all the work:
#Requires -Version 4
Function ConvertFrom-DistinguishedName
{
[CmdletBinding()]
[OutputType('System.Management.Automation.PSCustomObject')]
Param(
[Parameter(Position = 0, Mandatory)]
[Alias('DistinguishedName', 'Name')]
[ValidatePattern('^CN=.+?,(OU=.+?,)+DC=.+$')]
[string]
$Path
)
$local:ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
$WS = $Path -split ',' # working set
$User = $WS[0] -replace 'CN='
$Domain = $WS.Where({$PSItem.StartsWith('DC=')}).ToLower() -replace 'dc=' -join '.'
$OU = $WS.Where({$PSItem.StartsWith('OU=')}) -replace 'OU='
[array]::Reverse($OU)
[pscustomobject]#{
'User' = $User
'Domain' = $Domain
'OU' = $OU -join '\'
}
}
PS C:\> ConvertFrom-DistinguishedName 'CN=John Doe,OU=IT,OU=Support,OU=Department,OU=HQ,DC=FR,DC=CONTOSO,DC=COM'
User Domain OU
---- ------ --
John Doe fr.contoso.com HQ\Department\Support\IT
The end result? This converts your distinguished AD name to a PSCustomObject you can easily work with.
To get the domain out of the Distinguishedname, you will want to use -Split. Finally we can use -join to insert '.' between the DCs
This will store your domain string to $domain:
$dn = "CN=John Doe,OU=IT,OU=Support,OU=Department,OU=HQ,DC=FR,DC=CONTOSO,DC=COM"
$domain = $dn -Split "," | ? {$_ -like "DC=*"}
$domain = $domain -join "." -replace ("DC=", "")
Write-Host "Current Domain: " $domain
You should use the ^ to start from the beginning.
$str = 'CN=John Doe,OU=IT,OU=Support,OU=Department,OU=HQ,DC=FR,DC=CONTOSO,DC=COM'
$str = $str -replace '^.+?,DC',''
$str = $str -replace 'DC=',''
$str -replace ',','.'
Since nobody bothered explaining the behavior yet:
The replacement operation replaces every occurrence of the pattern .+?,DC in the string, so it first removes CN=John Doe,OU=IT,OU=Support,OU=Department,OU=HQ,DC, then continues where that replacement left off and removes =FR,DC, and then =CONTOSO,DC, leaving you with just =COM.
To avoid this behavior you need to anchor the expression at the beginning of the string (^), as others have already suggested. The second replacement for substituting the remaining ,DC= with dots can be daisy-chained to the first one, so you need just one statement:
$str -replace '^.*?,dc=' -replace ',dc=', '.'
I'm trying to replace part of a string in Powershell. However, the replacement string is not hardcoded, it's calculated from a function:
$text = "the image is -12345-"
$text = $text -replace "-(\d*)-", 'This is the image: $1'
Write-Host $text
This gives me the correct result:
"This is the image: 12345"
Now, I want to include the base64 encoded image. I can read the image from the id. I was hoping the following would work, but it doesn't:
function Get-Base64($path)
{
[convert]::ToBase64String((get-content $path -encoding byte))
}
$text -replace "-(\d*)-", "This is the image: $(Get-Base64 '$1')"
The reason that it doesn't work, is because it first passes $1 (the string, not the value of $1) to the function, executes it and only then does it do the replace. What I want to do is
Find the occurrence of the pattern
Replace each occurence with the pattern
For each replace:
Pass the capture group to the function
Use the value of the capture group to get the base64 image
inject the base64 image into the replacement
You can use the static Replace method from the [regex] class:
[regex]::Replace($text,'-(\d*)-',{param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
Alternatively you can define a regex object and use the Replace method of that object:
$re = [regex]'-(\d*)-'
$re.Replace($text, {param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
For better readability you could define the callback function (the scriptblock) in a separate variable and use that in the replacement:
$callback = {
param($match)
'This is the image: ' + (Get-Base64 $match.Groups[1].Value)
}
$re = [regex]'-(\d*)-'
$re.Replace($text, $callback)
PetSerAl's helpful answer is your only option in Windows PowerShell, as of v5.1.
PowerShell Core v6.1+ now offers a native PowerShell solution via an enhancement to the
-replace operator, which obviates the need to call [regex]::Replace():
Just as with [regex]::Replace(), you can now:
pass a script block as the -replace replacement operand, which must return the replacement string,
except that the match at hand (an instance of type [System.Text.RegularExpressions.Match]) is represented as automatic variable $_, as is customary in PowerShell.
Applied to your case:
$text -replace "-(\d*)-", { "This is the image: $(Get-Base64 $_.Groups[1].Value)" }
A simpler example:
# Increment the number embedded in a string:
PS> '42 years old' -replace '\d+', { [int] $_.Value + 1 }
43 years old
Here's another way. Use the -match operator, and then reference $matches. Note that $matches doesn't get set with arrays on the left side of the -match operator. $matches.1 is the first grouping formed by the ( ).
$text = "the image is -12345-"
function Get-Base64($path) {
[convert]::ToBase64String( (get-content $path -asbytestream) ) } # ps 6 ver
if (! (test-path 12345)) { echo hi > 12345 }
$text -match '-(\d*)-'
$text -replace '-(\d*)-', "$(Get-Base64 $matches.1)"
the image is aGkNCg==
Or to break it up even more:
$text -match '-(\d*)-'
$result = Get-Base64 $matches.1
$text -replace '-(\d*)-', $result