Cataster
Cataster

Reputation: 3521

How to replace last part of a string dynamically?

I have the following:

$file_input = "cube1_server1_partial.xml"
$CUBEName = [io.path]::GetFileNameWithoutExtension($file_input).ToUpper() -replace "_partial" #strips extension from $file_input

This results in: cube1_server1.

Now I have other file names that came into light, such as:

cube1_server1_full.xml

I want a comprehensive replacement that doesn't necessarily have to hard code the suffix, so instead of -replace "_partial".

It should be something like -replace "_*" from the end of a string.

How can I have a comprehensive replace? maybe with regex?

Upvotes: 1

Views: 142

Answers (3)

mklement0
mklement0

Reputation: 437638

Yet another solution:

PS> 'cube1_server1_partial.xml' -replace '(.*)_.*', '$1'
cube1_server1
  • (.*)_ greedily matches through the last _ and captures everything before it (.*) in the 1st capture group ((...)).

  • .* matches the rest, which ensures that the overall regex matches the entire input string.

  • Replacement string $1 then replaces the entire string with what the 1st capture group captured, which is everything before the last _.

See this answer for more information about the -replace operator.

Upvotes: 3

Lee_Dailey
Lee_Dailey

Reputation: 7479

this is yet another method to get the cleaned file name. [grin] however, if you have many such items to clean up, then the regex posted by Mathias R. Jessen is likely your best bet for speed.

what it does ...

  • split the string on the dot & save the parts into $Name & $Extension
  • split the $Name on _, skip the last item, rejoin the parts with _
  • join $WantedNamePart & $Extension with a .
  • display the results

the code ...

$FileName = 'cube1_server1_partial.xml'

$Name, $Extension = $FileName.Split('.')
$WantedNamePart = ($Name.Split('_') |
    Select-Object -SkipLast 1) -join '_'

$CleanedFileName = $WantedNamePart, $Extension -join '.'

$CleanedFileName

output ...

cube1_server1.xml

Upvotes: 3

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174485

If you want to remove the last _ and everything following it from a string, you have a couple of options.

Use String.LastIndexOf() and String.Remove():

$string = 'cube1_server1_partial'
$last_index = $string.LastIndexOf('_')
if($last_index -ne -1){
    $string = $string.Remove($last_index)
}

Or you could use the -replace regex operator with a more descriptive pattern:

$string = 'cube1_server1_partial'
$string -replace '(?<=.+)_[^_]*$'

The regex in the example above consists of:

(?<=  # positive look-behind assertion
  .+  # for 1 or more characters
)
_     # a literal underscore
[^_]* # any character that's NOT an underscore, 0 or more times
$     # followed by end of string

The look-behind ensure you don't end up with an empty string if the only _ occurs at position 0, eg. _partial would just return as is. For the non-regex method the equivalent would be to check for $last_index -gt 0 instead of -ne -1

Upvotes: 2

Related Questions