1
votes

I have a filepath, and I'm trying to remove the last two occurrences of the / character into . and also completely remove the '{}' via Powershell to then turn that into a variable.

So, turn this:

xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx

Into this:

xxx-xxx-xx\xxxxxxx\x\xxxx-xxxxx-xxxx.xxxxx.xxxxx

I've tried to get this working with the replace cmdlet, but this seems to focus more on replacing all occurrences or the first/last occurrence, which isn't my issue. Any guidance would be appreciated!

Edit:

So, I have an excel file and i'm creating a powershell script that uses a for each loop over every row, which amounts to thousands of entries. For each of those entries, I want to create a secondary variable that will take the full path, and save that path minus the last two slashes. Here's the portion of the script that i'm working on:

Foreach($script in $roboSource)
   {
    $logFileName = "$($script.a).txt".Replace('(?<=^[^\]+-[^\]+)-','.')
   } 

$script.a will output thousands of entries in this format: xxx-xxx-xx\xxxxxxx\x{xxxx-xxxxx-xxxx}\xxxxx\xxxxx Which is expected.

I want $logFileName to output this: xxx-xxx-xx\xxxxxxx\x\xxxx-xxxxx-xxxx.xxxxx.xxxxx

I'm just starting to understand regex, and I believe the capture group between the parenthesis should be catching at least one of the '\', but testing attempts show no changes after adding the replace+regex.

Please let me know if I can provide more info.

Thanks!

3
As an aside: Note that the .Replace method (of type [string]) uses literal substring replacement - no regexes supported. - mklement0

3 Answers

5
votes

You can do this in two fairly simply -replace operations:

  • Remove { and }
  • Replace the last two \:
$str = 'xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'
$str -replace '[{}]' -replace '\\([^\\]*)\\([^\\]*)$','.$1.$2'

The second pattern matches:

\\         # 1 literal '\'
(          # open first capture group
  [^\\]*   # 0 or more non-'\' characters
)          # close first capture group
\\         # 1 literal '\'
(          # open second capture group
  [^\\]*   # 0 or more non-'\' characters
)          # close second capture group
$          # end of string

Which we replace with the first and second capture group values, but with . before, instead of \: .$1.$2


If you're using PowerShell Core version 6.1 or newer, you can also take advantage of right-to-left -split:

($str -replace '[{}]' -split '\\',-3) -join '.'

-split '\\',-3 has the same effect as -split '\\',3, but splitting from the right rather than the left.

3
votes

A 2-step approach is simplest in this case:

# Input string.
$str = 'xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'

# Get everything before the "{"
$prefix = $str -replace '\{.+'

# Get everything starting with the "{", remove "{ and "}", 
# and replace "\" with "."
$suffix = $str.Substring($prefix.Length) -replace '[{}]' -replace '\\', '.'

# Output the combined result (or assign to $logFileName)
$prefix + $suffix

If you wanted to do it with a single -replace operation (with nesting), things get more complicated:

Note: This solution requires PowerShell Core (v6.1+)

$str -replace '(.+)\{(.+)\}(.+)',
  { $_.Groups[1].Value + $_.Groups[2].Value + ($_.Groups[3].Value -replace '\\', '.') }

Also see the elegant PS-Core-only -split based solution with a negative index (to split only a fixed number of tokens off the end) in Mathias R. Jessen's helpful answer.

2
votes

try this

$str='xxx-xxx-xx\xxxxxxx\x\{xxxx-xxxxx-xxxx}\xxxxx\xxxxx'

#remove  bracket and split for get array
$Array=$str -replace '[{}]' -split '\\'

#take all element except 2 last elements, and concat after last elems
"{0}.{1}.{2}" -f ($Array[0..($Array.Length -3)] -join '\'), $Array[-2], $Array[-1]