Skip to content

Instantly share code, notes, and snippets.

@spiralx
Created April 1, 2014 01:16
Show Gist options
  • Save spiralx/9905898 to your computer and use it in GitHub Desktop.
Save spiralx/9905898 to your computer and use it in GitHub Desktop.
Regular Expressions with Named Groups
/**
* Allows you to specify named groups in regular expressions like in Perl/Python/.NET/etc. You have to
* use a string to specify the regex, and the function returns an object that has `exec` and `replace`
* functions like a normal RegExp object, but matches they generate have keys for the values of the named
* groups.
*
* n = NamedRegExp("(?<protocol>http|ftp)://(?<host>[\\w-]+\\.com)(?<path>/.+\\.html)?$");
* res = n.exec("http://foobar.com"); -> res.protocol = http, res.host = foobar.com res.path = undefined
* res = n.exec("http://foobar.com/"); -> res.protocol = http, res.host = foobar.com res.path = /
* res = n.exec("http://foobar.com/index.html"); -> res.protocol = http, res.host = foobar.com res.path = /index.html
*
* n = NamedRegExp("(?<initial>[A-Z]) (?<surname>[A-Z][a-zA-Z]+)")
* n.replace("J Skinner, M Cow and F Baloney", function(m) {
* return m.surname + ", " + m.initial + ".";
* }) -> "Skinner, J., Cow M. and Baloney, F."
*
* @param {String} regex_str
* @param {String?} flags
* @return {NamedRegExp}
*/
function NamedRegExp(regex_str, flags) {
var
name_order = [null],
plain_regex = regex_str.replace(/\(\?<(\w+)>/g, function(match, name) {
var i = name_order.indexOf(name);
if (i == -1) {
i = name_order.push(name);
}
return "(";
}),
matches_extend = function(matches) {
if (matches) {
for (var i = 1; i < matches.length; i++) {
matches[name_order[i]] = matches[i];
}
}
return matches;
};
return {
exec: function(src) {
var
re = RegExp(plain_regex, flags),
matches = re.exec(src);
return matches_extend(matches);
},
replace: function(src, repl_func) {
var re = RegExp(plain_regex, "g" + flags);
return src.replace(re, function() {
var match = matches_extend(Array.from(arguments).slice(0, -2));
//console.dir(arguments);
return repl_func(match);
});
}
};
}
// --------------------------------------------------------------------
/**
* array_to_obj([1, 5, 6], "x y z") -> { x: 1, y: 5, z: 6 }
* array_to_obj([undefined, 4], ["score", "level"]) -> { level: 4 }
*/
function arr_to_obj(arr, names) {
var keys = Array.isArray(names) ? names : names.split(" "),
obj = {},
i = 0;
if (arr.length > keys.length) {
throw Error("Not enough key names!");
}
for (; i < keys.length; i++) {
if (typeof arr[i] !== "undefined") {
obj[keys[i]] = arr[i];
}
}
return obj;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment