Nick H.
Nick H.

Reputation: 1616

How can I get my regex method to return all path matches?

I'm trying to parse out our backup paths, which are network shares, from the backup command used.

This is what the backup command looks like:

BACKUP DATABASE [UnitTestDB] TO DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_2.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_3.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_4.bak' WITH CHECKSUM, COMPRESSION

What I want is to get all of the network shares out....

\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak
\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_2.bak
\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_3.bak
\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_4.bak

No single quotes, just the values.

I can get it working on http://regexstorm.net/tester but I can't seem to translate it back to PowerShell terms. This is the matching expression that works in the tester...

[DISK = N'](\S*)[']

But PowerShell only returns one out of the four matches and it returns the N' as well. It has to be some syntax error I'm not catching.

Output:

Groups   : { N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak', 
           N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak}
Success  : True
Captures : { N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak'}
Index    : 38
Length   : 100
Value    :  N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak'

Here's the code I have so far...

$backupCommand = "BACKUP DATABASE [UnitTestDB] TO DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_2.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_3.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_4.bak' WITH CHECKSUM, COMPRESSION"

[regex]::Match($backupCommand,"[DISK = N'](\S*)[']")

Upvotes: 1

Views: 70

Answers (2)

Matt
Matt

Reputation: 46710

Lots of options when it comes to regex solutions. Martin's answer explains why you were not getting the results you expected and that you needed to return all results by using the static method [regex]::Matches. You can also use Select-String with the -AllMatches switch to do the same thing. Since it returns matchinfo objects you also need to do a little post processing.

I used a different regex based on your source data. Return matches between sets of double quotes. I could have made this more terse if I used lookaheads and behinds but I wanted to keep the regex simple.

$regex = "'(.*?)'"

($data | Select-String -Pattern $regex -AllMatches).Matches | 
    ForEach-Object{$_.Groups[1].Value}

Upvotes: 2

Martin Brandl
Martin Brandl

Reputation: 58971

Use [regex]::Matches instead of Match to get multiple matches. To get the capture group, you have to access the Property Groups[1].Value. Also, your regex was wrong, you have to omit the square brackets:

$backupCommand = "BACKUP DATABASE [UnitTestDB] TO DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_2.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_3.bak', DISK = N'\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_4.bak' WITH CHECKSUM, COMPRESSION"

[regex]::Matches($backupCommand,"DISK = N'(\S*)[']") | Foreach {
    $_.Groups[1].Value
}

Output:

\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_1.bak
\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_2.bak
\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_3.bak
\\networkshare\sqldb\servername\UnitTestDB\FULL\servername_UnitTestDB_FULL_20160614_231500_4.bak

This will work, but since your capture group will fail if the network path contains an empty space, I would change the regex to capture all until the trailing ':

DISK = N'([^']+)

Regular expression visualization

Upvotes: 2

Related Questions