views:

355

answers:

3

How can I emulate the SQL keyword LIKE in JavaScript. For those of you who don't know what LIKE is, it's a very simple regex which only supports the wildcards %, which matches 0 or more characters, and _ which matches exactly one character.

However, it's not just possible to do something like

var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null;

because the pattern might contain dots, stars and any other special regex char.

Edit: Anti-nitpicking paren.

+1  A: 

If you want to use a regex, you can wrap each character of the string in square-brackets. Then you only have a few characters to escape.

But a better option might be to truncate the target strings so the length matches your search string and check for equality.

Joel Coehoorn
+3  A: 

What you have will work as long as you first escape the regex characters in your pattern. Below is one example from Simon Willison’s blog:

RegExp.escape = function(text) {
  if (!arguments.callee.sRE) {
    var specials = [
      '/', '.', '*', '+', '?', '|',
      '(', ')', '[', ']', '{', '}', '\\'
    ];
    arguments.callee.sRE = new RegExp(
      '(\\' + specials.join('|\\') + ')', 'g'
    );
  }
  return text.replace(arguments.callee.sRE, '\\$1');
}

You could then implement your code as:

likeExpr = RegExp.escape(likeExpr);
var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null;
Chris Pebble
Assuming what you have already - `RegExp.like = function (text) { return new RegExp("^"+(RegExp.escape(text).replace(/%/g, ".*").replace(/_/g, "."))+"$"); }` might be a bit more reusable for him.
gnarf
That `Regex.escape` implementation is quite of an overkill. First of all, `arguments.callee` occurrence prevents some of the optimizations in modern browsers (and is deprecated in ES5-strict), so it's better to avoid it when possible. Second, there's an unnecessary escaping of characters, when instead they could be placed in a character class.Here's a smaller (and most likely faster) version that we use in Prototype.js - `RegExp.escape = function(str) { return str.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); };`
kangax
+1  A: 

Here's a function I use, based on PHP's preg_quote function:

function regex_quote(str) {
  return str.replace(new RegExp("([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])", "g"), "\\$1");
}

So your line would now be:

var match = new RegEx(regex_quote(likeExpr).replace("%", ".*").replace("_", ".")).exec(str) != null;
Kip