nom
nom

Reputation: 115

Powershell split on last instance of character per line

I am attempting to use Powershell to split an array of strings on the last occurrence of a delimiter (/) for each line. A sample input array:

classes/CaseHandler.cls
email/Insurance_Templates/Policy_Amend_Approval_Request.emailcode here

Running the command $arr -split '/' gives the following result:

classes
CaseHandler.cls
email
Insurance_Templates
Policy_Amend_Approval_Request.email

This is fine for the class file as I need the folder path on the first line and the filename on the second. There are however a number of files in the input that have a deeper file path. I'm looking for a way to split each line of the array only on the last occurrence of the / character. The required output being:

classes
CaseHandler.cls
email/Insurance_Templates
Policy_Amend_Approval_request.email

I've tried a number of approaches using substring methods but can't figure out how to incorporate this into splitting an array line by line. Any assistance on this would be greatly appreciated.

Upvotes: 5

Views: 8494

Answers (2)

jdgregson
jdgregson

Reputation: 1587

I'm providing this answer because the accepted answer proposed an alternate solution to OP's problem and left the question in the title unanswered. Since that is the question Google brought me here for, I'll leave my solution here for future readers.

The quickest way I've found to do this is with regular expressions. For example, let's say you want to separate the host and port from a host:port pair. It would be easy to split on :, but if the host is an IPv6 address, we'll be splitting in the wrong spot.

Instead, the following regular expression could be used: ([0-9A-z.\-:]*):([0-9]*):

> $client1 = "127.0.0.1:65535"
> $server1, $port1 = if ($client1 -match "([0-9A-z.\-:]*):([0-9]*)") {$matches[1], $matches[2]}
> Write-Host "The server is $server1 and the port is $port1"
The server is 127.0.0.1 and the port is 65535

> $client2 = "[2001:db8::1]:8123"
> $server2, $port2 = if ($client2 -match "([0-9A-z.\-:]*):([0-9]*)") {$matches[1], $matches[2]}
> Write-Host "The server is $server2 and the port is $port2"
The server is [2001:db8::1] and the port is 8123

> $client3 = "edge-http-uswest-004.example.com:8920"
> $server3, $port3 = if ($client3 -match "([0-9A-z.\-:]*):([0-9]*)") {$matches[1], $matches[2]}
> Write-Host "The server is $server3 and the port is $port3"
The server is edge-http-uswest-004.example.com and the port is 8920

> $client4 = "2034:a9c2::0102:009a:443"
> $server4, $port4 = if ($client4 -match "([0-9A-z.\-:]*):([0-9]*)") {$matches[1], $matches[2]}
> Write-Host "The server is $server4 and the port is $port4"
The server is 2034:a9c2::0102:009a and the port is 443

It is fairly forgiving when unexpected data is encountered:

> $client5 = "localhost"
> $server5, $port5 = if ($client5 -match "([0-9A-z.\-:]*):([0-9]*)") {$matches[1], $matches[2]}
> Write-Host "The server is $server5 and the port is $port5"
The server is  and the port is

And with a new regular expression, it can be used to solve OP's problem (though I'd still prefer the accepted answer for this purpose):

> $path = "C:\Program Files (x86)\Example Inc.\example.exe"
> $dir, $file = if ($path -match "([A-z0-9:.\ ()]*)\\([A-z0-9.]*)") {$matches[1], $matches[2]}
> Write-Host "Directory: $dir`nFile: $file"
Directory: C:\Program Files (x86)\Example Inc.
File: example.exe

Upvotes: 4

Don Cruickshank
Don Cruickshank

Reputation: 5938

Since you're dealing with filenames, you should use the Split-Path cmdlet:

PS> $paths = "classes/CaseHandler.cls", `
             "email/Insurance_Templates/Policy_Amend_Approval_Request.emailcode"

To get the directory parts:

PS> $paths | Split-Path
classes
email\Insurance_Templates

To get the file parts:

PS> $paths | Split-Path -Leaf
CaseHandler.cls
Policy_Amend_Approval_Request.emailcode

And putting those together to get the format you're after:

PS> $paths | % { Split-Path $_ ; Split-Path -Leaf $_ }
classes
CaseHandler.cls
email\Insurance_Templates
Policy_Amend_Approval_Request.emailcode

Upvotes: 7

Related Questions