Thursday, April 12, 2007

Dynamic Regular Expressions in Javascript

I'd just to give credit to a great post by John-Paul Bader about Dynamic Regular Expressions in Javascript. It saved a few hours of searching around for obsolete documentation.

Using regular expressions is easy enough...

var result String('The yellow fox has big eyes').match(/\b\w+\b/gi);
But it isn't so straight-forward when you want to create a regular expression on the fly.
Let's say I want to find all words beginning with a certain letter.
var letter = 'y';
You cannot do any of the following (warning, bad code ahead!)
var result String('The yellow fox has big eyes').match(/\bletter\w+\b/gi);
var result String('The yellow fox has big eyes').match(/\b/ + letter + /\w+\b/gi);
var result String('The yellow fox has big eyes').match(/\b' + letter + '\w+\b/gi);
The only way to make it work is to compile a new regular expression during run-time, using the RegExp object. I won't into details, but the syntax is simple:
var rx = new RegExp(String pattern, String options);
Where pattern is you expression and options are your usual g (global), i (ignore case), m (multi-line) switches.

So you'd expect this to work...
var search = new RegExp('\b'+letter+'\w+\b', 'gi');
But that still isn't quite right. The backslash is a special escape character in Javascript strings. This causes the code above to build a regular expression like this byw+b, but what we actually want is this: \by\w+\b.

Which brings us to the final step in this journey. The correct way to work with truly dynamic regular expressions is...
var search = new RegExp('\\b'+letter+'\\w+\\b', 'gi');
So, to sum up:
  1. Put your regular expression in a string,
    ie: var pattern = '\b\w+\b';

  2. Escape Javascript's escape characters,
    ie: var pattern = '\\b\\w+\\b';

  3. Use the RegExp builder to compile a regular expression on the fly,
    ie: test = new RegExp(pattern, 'gi');
And that's it!

3 comments:

Nathan said...

Awesome. This was just what I needed.

Crazycat said...

Perfect! I've been looking for how to do this for days now!

Karsten said...

Great, just fine, short and what i was locking for!