Extending Regular Expressions

You know the prob­lem with reg­u­lar expres­sions in JavaS­cript?: There’s not enough to do. Sure, you can use its meth­ods against strings but there’s noth­ing that allows you to manip­u­late the actual expres­sions. Where is the prop­erty for all the mod­i­fi­ers? How can you add or remove a mod­i­fier? The simple answer is that it isn’t pos­sible. The long and com­plic­ated way says that it is. The only prob­lem is that the code is a little bit ugly:

RegExp.prototype.modifiers = function() {
	return /^\/(.+)\/([gim]+?)$/i.exec(this.toString())[2].split('');
};

Don’t say I didn’t warn you.

In short, that method con­verts the expres­sion to a string and then executes another reg­u­lar expres­sion with it. This new reg­u­lar expres­sion takes away the main pat­tern and leaves the mod­i­fi­ers in a string. That string is then split into indi­vidual char­ac­ters so you have an array of them (for example: ['g', 'i']).

This magic reg­u­lar expres­sion can also be used for extract­ing a pat­tern, which, in turn, allows you to rebuild it with the RegExp con­structor — mod­i­fi­ers included. This is the method for extract­ing the pattern:

RegExp.prototype.pattern = function() {
	return /^\/(.+)\/([gim]+?)$/i.exec(this.toString())[1];
};

Rebuild­ing it is as simple as this:

var original = /\s+/g;

var pattern = original.pattern();
var modifiers = original.modifiers().join('');

var better = new RegExp(pattern, modifiers);

So, put­ting two and two together, if we can extract the pat­tern and the mod­i­fi­ers, and rebuild it, what’s stop­ping us from chan­ging it along the way? Enter addModifiers and removeModifiers:

RegExp.prototype.addModifiers = function(modifiers) {
	return new RegExp(this.pattern(), this.modifiers().join('') + modifiers.join(''));
};

RegExp.prototype.removeModifiers = function(modifiers) {
	return new RegExp(this.pattern(), this.modifiers().join('').replace(new RegExp(modifiers.join('|'), 'i'), ''));
};

With the addModifiers method, you may have noticed that I haven’t bothered to check for the exist­ing mod­i­fi­ers. This is because you can duplic­ate a mod­i­fier on a reg­u­lar expres­sion and it won’t mat­ter as it’ll only be coun­ted once. Both of these meth­ods allow mul­tiple mod­i­fi­ers and require them to be an array (['g', 'i']):

var original = /\s+/g;

original = original.addModifiers(['i']); // /\s+/gi
original = original.removeModifiers(['g']); // /\s+/i

pattern = original.pattern(); // '\s+'
modifiers = original.modifiers(); ['i']

Comments

No responses have been made so far. Add your comments.

    What do you think? Leave a comment...