Custom Regex Components in Swift

The Missing Piece in Your Regex Toolkit

published on April 13, 2025

In a previous article we have looked at how powerful the Swift regex system is. We have gone through all the options from hardcoded regex strings to regex literals and finally the regex builder introduced in Swift 5.7. In this article we are going to look at another clever way for working with complex regular expressions, the RegexComponent.

This often-overlooked feature provides a modular approach to regex construction, allowing developers to encapsulate complex patterns into reusable, composable components. As applications grow in complexity, maintaining and debugging regular expressions can quickly become challenging. This is where RegexComponent shines by offering a more structured and maintainable solution. Whether you're parsing structured text, validating user input, or extracting information from documents, understanding how to leverage RegexComponent can significantly enhance your Swift code's readability and flexibility.

What is a regex component?

This of a regex component as of any component in a programming context. It encapsulates certain parts of the logic for reusability. RegextComponents are the perfect tool for applications that need to use the same patter over and over again.

Take the following example:

let regex = Regex {
    OneOrMore {
        CharacterClass(
            .anyOf("-."),
            .word,
            .digit
        )
    }
    "@"
    OneOrMore {
        CharacterClass(
            .anyOf("-"),
            .word
        )
    }
    "."
    ChoiceOf {
        "com"
        "de"
    }
}

This regex is meant for matching email addresses.

💡 Note: This article is not about email matching patters, thus the presented pattern may not be perfect but it can present the main concept of this article well

Now, imagine that your application requires you to use this pattern over and over again. You can find a way to share the regex variable accross your codebase but what if you need to encapsulate it in some other patterns? Like you need to find all rows that have the following format: [name]: [email]

In this case, your regex variable will not be much of a help, and that is where the RegexComponent comes into play. Creating such a component is very simple. We just have to conform the RegexComponent protocol and implment the only requirement which is var regex: Regex { get }

Like this:

struct EmailPattern: RegexComponent {
    var regex: Regex<Substring> {
        Regex {
            OneOrMore {
                CharacterClass(
                    .anyOf("-."),
                    .word,
                    .digit
                )
            }
            "@"
            OneOrMore {
                CharacterClass(
                    .anyOf("-"),
                    .word
                )
            }
            "."
            ChoiceOf {
                "com"
                "de"
            }
        }
    }
}

After this, we can use our email component in other regular expressions like this:

let regex = Regex {
    "Email: "
    EmailComponent()
}
Follow me on X