I'm a fan of regular expressions and tend to be the go-to guy on teams when it comes to (concoct|conjur)ing patterns. I've also answered a good amount of regex related questions on StackOverflow.

One of the questions that frequently gets asked is how to construct a pattern that enforces passphrase/password validation with a number of criteria. These are the rules you typically see when signing up on the majority of websites: your password must include at least 1 uppercase letter, 1 lowercase letter, 1 digit, 3 oz. Unicorn tears, and 16 scruples of Fluxweed... you get the idea.

Other questions revealed a host of handy techniques that I wanted to capture, such as splitting strings and including the delimiters, trimming whitespace, and formatting camel case values.

Enter Regextra

A little over a year ago I started working on a library to address these problems and capture useful solutions. I've been working on it on and off and recently devoted much more time to it to add some finishing touches before releasing it on NuGet. Without further ado, I'm finally happy to reveal it!

Regextra (pronounced "Rej-extra") is an open-source .NET library written in C#. It's well tested, with over 200 unit tests.

Currently, the library includes the following features:

  • Passphrase Regex Builder
  • Named Template Formatting
  • Useful regex/string methods

Over time I hope to add other useful features, and would love to hear any community feedback on what the library accomplishes today. The goal of this project was to address common scenarios, however that's not to be confused with amassing all sorts of patterns. This is more of a helpful utility, not an encyclopedia of patterns.

Getting Started

  • Check out the wiki
  • Visit the project's demo site for a chance to try out some client-side validation (using the patterns produced by the PassphraseRegex builder)
  • The extensive test suite is worth a glance

Regextra is available via NuGet:

PM> Install-Package Regextra

Passphrase Regex Builder

A common question I've seen on StackOverflow is how to write code that enforces strong passphrase or password rules. Popular responses tend to tackle the problem by using a regex with look-aheads. I've seen this so much that I decided to have fun writing a solution that allowed people to produce regex patterns that would enforce such rules.

Example usage

The following code generates a pattern to enforce a password of 8-25 characters that requires at least two lowercase letters in the range of a-z and numbers excluding those in the range of 0-4 (i.e., numbers in the 5-9 range are acceptable).

var builder = PassphraseRegex.With.MinLength(8)
                                  .MaxLength(25)
                                  .IncludesRange('a', 'z')
                                  .WithMinimumOccurrenceOf(2)
                                  .ExcludesRange(0, 4);

PassphraseRegexResult result = builder.ToRegex();

if (result.IsValid)
{
    if (result.Regex.IsMatch(input))
    {
        // passphrase meets requirements
    }
    else
    {
        // passphrase is no good
    }
}
else
{
    // check the regex parse exception message for the generated pattern
    Console.WriteLine(result.Error);
}

Refer to the PassphraseRegex wiki for further details and examples.

Template Formatting

Template formatting allows you to perform named formatting on a string template using an object's matching properties. It's available via the static Template.Format method and the string extension method, FormatTemplate. The formatter features:

  • Nested properties formatting
  • Dictionary formatting
  • Standard/Custom string formatting
  • Escaping of properties
  • Detailed exception messages to pinpoint missing properties
  • Great performance (in part thanks to FastMember)

Example usage

var order = new
{
    Description = "Widget",
    OrderDate = DateTime.Now,
    Details = new
    {
        UnitPrice = 1500
    }
};

string template = "We just shipped your order of '{Description}', placed on {OrderDate:d}. Your {{credit}} card will be billed {Details.UnitPrice:C}.";

string result = Template.Format(template, order);
// or use the extension: template.FormatTemplate(order);

The result of the code is:

We just shipped your order of 'Widget', placed on 2/28/2014. Your {credit} card will be billed $1,500.00.

Refer to the Template wiki for further details and examples.

RegexUtility Class

This static class features a couple of helpful methods, such as:

  • Split Methods

    • Split
    • SplitRemoveEmptyEntries
    • SplitIncludeDelimiters
    • SplitMatchWholeWords
    • SplitTrimWhitespace
  • Formatting Methods

    • TrimWhitespace
    • FormatCamelCase
  • Named Groups Conversion Methods

    • MatchesToNamedGroupsDictionaries
    • MatchesToNamedGroupsLookup

Split and Include Delimiters

string input = "123xx456yy789";
string[] delimiters = { "xx", "yy" };
var result = RegexUtility.SplitIncludeDelimiters(input, delimiters);
// { "123", "xx", "456", "yy", "789" }

Combining Split Options

string input = "StackOverflow Stack OverStack";
string[] delimiters = { "Stack" };
var splitOptions = SplitOptions.TrimWhitespace | SplitOptions.RemoveEmptyEntries;
var result = RegexUtility.Split(input, delimiters, splitOptions: splitOptions);
// { "Overflow", "Over" }

Trimming Whitespace

var result = RegexUtility.TrimWhitespace("   Hello    World   ");
// "Hello World"

FormatCamelCase

Formats PascalCase (upper CamelCase) and (lower) camelCase words to a friendly format separated by the given delimiter (space by default).

It properly handles acronyms too. For example "XML" is properly preserved when given an input of "PickUpXMLInFiveDays". The result is "Pick Up XML In Five Days".

RegexUtility.FormatCamelCase("PascalCase")        // Pascal Case
RegexUtility.FormatCamelCase("camelCase42", "_")  // camel_Case_42

Matches To Named Groups Dictionaries

Returns an array of Dictionary<string, string> of each match with the named groups as the keys, and the group's corresponding value.

var input = "123-456-7890 hello 098-765-4321";
var pattern = @"(?<AreaCode>\d{3})-(?<First>\d{3})-(?<Last>\d{4})";
var results = RegexUtility.MatchesToNamedGroupsDictionaries(input, pattern);

This code returns the following result:

Named Groups Dictionaries

Refer to the RegexUtility wiki for further details and examples.

Check it out, Feedback Welcome

Regextra's source is on GitHub, and you can grab it from NuGet.

Please try it out and let me know what you think. Feedback is welcome, so feel free to leave comments or open issues.