1

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 doesnt 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?

Cataster
  • 3,081
  • 5
  • 32
  • 79

3 Answers3

3

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
Lee_Dailey
  • 7,292
  • 2
  • 22
  • 26
3

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
2

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

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206