Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emulating SQL LIKE in JavaScript

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 characters.

like image 598
erikkallen Avatar asked Aug 21 '09 20:08

erikkallen


Video Answer


2 Answers

An old question but there are actually no good answers here. TSQL LIKE expressions can contain square-bracket escaped sections that are already almost valid regular expressions and allow for matching % and _. E.g.:

'75%' LIKE '75[%]'
'[foo]' LIKE '[[]foo]' -- ugh

Here's my function to convert a LIKE expression into a RegExp. The input is split into square-bracket and non-square-bracket sections. The square-bracket sections just need backslash escaping and the non-square-bracket sections are fully escaped while the % and _ directives are converted to regular expressions.

const likeRegExp = (expression, caseSensitive = false) =>
    new RegExp(`^${
        expression.split(/(\[.+?\])/g)
        .map((s, i) => i % 2 ?
            s.replace(/\\/g, '\\\\') :
            s.replace(/[-\/\\^$*+?.()|[\]{}%_]/g, m => {
                switch(m) {
                    case '%': return '.*';
                    case '_': return '.';
                    default: return `\\${m}`;
                }
            })
        ).join('')
    }$`, caseSensitive ? '' : 'i');
like image 168
JohnLock Avatar answered Oct 07 '22 22:10

JohnLock


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;
like image 42
Chris Van Opstal Avatar answered Oct 08 '22 00:10

Chris Van Opstal