Regex to match path

Viewed 243

I trying to validate user entered string is correct relative path or not.

  • It should not start with assets/
  • It should not end with /
  • It should not end with any file extension like .html or .php or .jpg
  • It should not contain dot .

I am trying with below regex, but it is not working correctly.

^([a-z]:)*(\/*(\.*[a-z0-9]+\/)*(\.*[a-z0-9]+))

My test cases

Valid path

  • sample/hello/images
  • sample/hello_vid/user/data
  • test/123/user_live/images

Invalid path

  • assets/sample/hello/images
  • sample/hello_vid/user/data/
  • test/123/user_live/images/index.html
  • hii/sk.123/data
  • ok/bye/last.exe
5 Answers

Alternative "readable" approach ;)

public static bool IsValidPath(this string path)
{
    if (string.IsNullOrEmpty(path)) return false;
    if (path.StartsWith("assets/")) return false;
    if (path.EndsWith("/")) return false;
    if (path.Contains(".")) return false;

    return true;
}

// Usage
var value = "sample/hello/images";
if (value.IsValidPath())
{
    // use the value...
}

If you also want to match the underscore, you could add it to the character class. To prevent matching assets/ at the start, you could use a negative lookahead.

^(?!assets/)[a-z0-9_]+(?:/[a-z0-9_]+)+$
  • ^ Start of string
  • (?!assets/) Assert what is directly to the right is not assets/
  • [a-z0-9_]+ Repeat 1+ times any of the listed, including the underscore
  • (?:/[a-z0-9_]+)+ Repeat 1+ times a / and 1+ times any of the listed
  • $ End of string

Regex demo

Or you could use \w instead of the character class

^(?!assets/)\w+(?:/\w+)+$

This works for your test cases.

Regex explained:
^(?!assets/) # It should not start with assets/
[^\.]+       # It should not contain dot (file extensions contain a dot)
(?<!/)$      # It should not end with /

Regex in one line:
^(?!assets/)[^\.]+(?<!/)$

You may try below regex to achieve your purpose:

^(?!assets\/)[^.]*?$(?<!\/\r?$)

Explanation of the above regex:

^, $ - Represents start and end of line respectively.

(?!assets\/) - Represents a negative look-ahead not matching the test strings which start with assets\.

[^.]*? - Matches everything lazily other than .. This case will cover the file extensions too so no need to check them again.

(?<!\/\r?$) - Represents negative look behind not matching the test string if it contains \ as the last character.

You can find the demo of the above regex in here.

Pictorial Representation Implementation in C#

using System;
using System.Text.RegularExpressions;

public class Example
{
    public static void Main()
    {
        string pattern = @"^(?!assets\/)[^.]*?$(?<!\/\r?$)";
        string input = @"sample/hello/images
sample/hello_vid/user/data
test/123/user_live/images
assets/sample/hello/images
sample/hello_vid/user/data/
test/123/user_live/images/index.html
hii/sk.123/data
ok/bye/last.exe";
        RegexOptions options = RegexOptions.Multiline;
        
        foreach (Match m in Regex.Matches(input, pattern, options))
        {
            Console.WriteLine(m.Value);
        }
    }
}

You can find the sample run of the above code in here.

The following regex should be fine for the scenarios you have mentioned:

^((?!(assets\/))(?! )([a-zA-Z0-9_ ]+(?<! )\/(?! ))+[a-zA-Z0-9_ ]+)$

In addition to the scenarios in the questions, I have also taken care of a folder name not starting or ending with spaces.

Related