So, the scenario is that you want to do some specific validation or matching, but part of what you're validating or matching will decide how the rest is validated or matched. For example, in my scenario I have a field in the database that will store a report destination in the URI format that can be either for e-mail, FTP, or a file (mailto://, ftp://, or file://). You could create three regular expressions and evaluate each, but that can be klunky especially if you're doing on the fly validation through a control like the Infragistics UltraWinGrid which allows you to set a regular expression as a validator on the column.
Alternations for expressions are what you need. Specifically, the .NET Framework specifies the following format for the alternation expression:
(?(expression)yes|no)
The easiest way to specify the expression is as a named group. And then yes and no become the remaining patterns to match if the named group specified in the expression has a match. Therefore, for my scenario I could write the shell of my regular expression as (ignore case option is set):
^((?<isMail>mailto)|(?<isFtp>ftp)|(?<isFile>file)):\/\/(?(isMail)yes|(?(isFtp)yes|no))$
This basically could be read as:
- Match the protocol as "mailto", "ftp", or "file"
- If we matched the protocol as "mailto" then
- Match the rest of the string as an e-mail address
- Else if we matched the protocol as "ftp" then
- Match the rest of the string as an FTP address
- Else
- Match the rest of the string as a file
From this point, you need to determine the regular expressions to match the mail, FTP, and file format. I used the following:
e-mail: ([\w\-\.]+)@((\[([0-9]{1,3}\.){3}[0-9]{1,3}\])|(([\w\-]+\.)+)([a-zA-Z]{2,4}))
ftp: (?:[\w.]+\/?)|(([A-Z]:\\[^/:\*\?<>\|]+\.\w{2,6})
file: (\\{2}[^/:\*\?<>\|]+\.\w{2,6})
At this point, it's just a matter of putting the values into the format I came up with earlier and I have a single regular expression to match the URIs that I care about.
^((?<isMail>mailto)|(?<isFtp>ftp)|(?<isFile>file)):\/\/(?(isMail)([\w\-\.]+)@((\[([0-9]{1,3}\.){3}[0-9]{1,3}\])|(([\w\-]+\.)+)([a-zA-Z]{2,4}))|(?(isFtp)(?:[\w.]+\/?)|(([A-Z]:\\[^/:\*\?<>\|]+\.\w{2,6})|(\\{2}[^/:\*\?<>\|]+\.\w{2,6}))))$