Most computer savvy persons are familiar with using wildcards when listing files and similar operations. Wildcards are quite easy to understand and use. An asterisk * means match anything, and the lesser known question mark ? matches a single character. So when creating our own applications we often want to give our users the ability to search with wildcards. The problem is that most programming languages don’t have a wildcard string matching functionality. But it is actually quite easy to implement on your own. All you need is to use Regular Expressions in a clever way.
Wildcards can be seen as a subset of RegEx; anything you can do with wildcard can also be done with RegEx. In RegEx the period (.) symbolizes any character. We can add an asterisk (star) after the period (.*). The * quantifier tells RegEx to search for zero or more of the preceding value, in this case any character. That sounds a lot like the asterisk in wildcards, doesn’t it? Similarly, the ? modifier means zero or one of the previous value.
So what we need to do is to convert our wildcard search into a RegEx search. This outlines the process:
- First we need to escape the search string to convert any special character in RegEx into character literals.
- Next, locate the wildcards and convert them into proper RegEx patterns.
- You probably also want to set the RegEx match to be case insensitive.
This can be used in all programming languages that support Regular Expressions. Exact syntax and RegEx dialect may vary though. Here are two examples that I made, one for C# and one for JavaScript:
C#
1 2 3 4 5 6 7 8 |
public static bool WildcardMatch(string find, string source) { find = Regex.Escape( find ); find = find.Replace( "\\*", ".*" ); find = find.Replace( "\\?", "." ); Regex regex = new Regex( find, RegexOptions.IgnoreCase ); return regex.IsMatch( source ); } |
JavaScript
1 2 3 4 5 6 7 |
function wildcardMatch(find, source) { find = find.replace(/[\-\[\]\/\{\}\(\)\+\.\\\^\$\|]/g, "\\$&"); find = find.replace(/\*/g, ".*"); find = find.replace(/\?/g, "."); var regEx = new RegExp(find, "i"); return regEx.test(source); } |
When implementing this in your own code, you need to think through how you want your search functionality to work. Perhaps you want case sensitive search? How should the beginning and end of strings be handled? Is the “greedy” property of RegEx desirable? Perhaps you need to add some more RegEx to control such behavior.
Resources:
Interesting post, these codes are working, thanks.
:)