Path validation - My RegEx is matching a malformed path and I can't figure out why

Viewed 140

This is my current expression: https://regex101.com/r/BertHu/4/

^(?:(?:[a-z]:|\\\\[a-z0-9_.$●-]+\\[a-z0-9_.$●-]+)\\|\\?[^\\\/:*?"<>|\r\n]+\\?)*(?:[^\\\/:*?"<>|\r\n]+\\)*[^\\\/:*?"<>|\r\n]*$

The regular expression I'm using is based on this implementation from Oreilly.

Here's a breakdown (I had to fix some un-escaped characters from Oreilly's expression):

(?:(?:[a-z]:|\\\\[a-z0-9_.$\●-]+\\[a-z0-9_.$\●-]+)\\|  # Drive
\\?[^\\\/:*?"<>|\r\n]+\\?)                             # Relative path
(?:[^\\\/:*?"<>|\r\n]+\\)*                             # Folder
[^\\\/:*?"<>|\r\n]*                                    # File

I'm implementing this in PowerShell, and the expression will be case-insensitive.

The problem that I'm running into is that it's matching the following malformed path (and I'm sure more that are similar): C:\foo\C:\bar

I can't understand exactly why this is happening, but I believe it has something to do with the drive portion of the expression:

^(?:(?:[a-z]:|\\\\[a-z0-9_.$●-]+\\[a-z0-9_.$●-]+)\\|

I don't know how to exclude a second : from the above. Maybe I'm completely overlooking something obvious.

Any help at all would be tremendously appreciated as I've spent all day working on this expression.

Thanks much.

1 Answers

When testing regular expressions at regex101.com, and some other regex testing sites, you can select parts of the pattern to see where they end and if they are quantified or not. Here, I clicked the first (?: and saw that

enter image description here

The group is meant to match zero or more occurrences of

  • (?:[a-z]:|\\\\[a-z0-9_.$●-]+\\[a-z0-9_.$●-]+)\\ - a letter and a :, or a \ and to occurrences of \\ and one or more alphanumeric, underscore, ., $, , - chars, and then a \ char
  • | - or
  • \\?[^\\\/:*?"<>|\r\n]+\\? - an optional \, one or more chars other than \, /, :, *, ?, ", <, >, |, CR and LF chars, and an optional \ char.

So, although the second alternative does not allow a semi-colon, the first one does, and as they repeat, they match parts of string consecutively.

Removing that asterisk will solve the issue as the rest of the pattern already matches valid file name chars.

^(?:(?:[a-z]:|\\\\[a-z0-9_.$●-]+\\[a-z0-9_.$●-]+)\\|\\?[^\\/:*?"<>|\r\n]+\\?)(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$

See the regex demo.

Note you do not need to escape forward slashes in Powershell regex patterns (and in any regex patterns that are defined with string literals (C#, Java, etc.)) since forward slashes are not special regex metacharacters.

Related