14 Stimmen

Emulieren von SQL LIKE in JavaScript

Wie kann ich das SQL-Schlüsselwort LIKE in JavaScript emulieren?

Für diejenigen unter Ihnen, die nicht wissen, was LIKE ist: Es handelt sich um eine sehr einfache Regex, die nur die Platzhalter % unterstützt, die null oder mehr Zeichen entsprechen, und _, das genau ein Zeichen entspricht.

Allerdings ist es nicht nur möglich, etwas wie folgt zu tun:

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

...weil das Muster Punkte, Sterne und andere spezielle Regex-Zeichen enthalten könnte.

0 Stimmen

Fyi- in Ihrem Beispielcode fehlt eine schließende Klammer vor ".exec"

0 Stimmen

@C.barlow: Zögern Sie nicht, ältere 'edit: .. blah'-Markierungen beim Bearbeiten zu entfernen. Streben Sie nach der "besten eigenständigen Frage"; die Bearbeitungsgeschichte ist für alle sichtbar, daher ist es nicht notwendig, Kommentare beizubehalten. :)

0 Stimmen

Versteht nicht direkt, wonach du suchst; Wenn du jedoch nur nach einer Übereinstimmung mit einem beliebigen Text suchst, ist der einfachste Weg, die Syntax includes zu verwenden: if(evalText.includes(searchText){ ... }

12voto

Chris Van Opstal Punkte 34697

Was du hast, wird funktionieren, solange du zuerst die Regex-Zeichen in deinem Muster escapst. Hier ist ein Beispiel von Simon Willisons 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');
}

Dann könnten Sie Ihren Code wie folgt implementieren:

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

2 Stimmen

Angenommen, was du bereits hast - RegExp.like = function (text) { return new RegExp("^"+(RegExp.escape(text).replace(/%/g, ".*").replace(/_/g, "."))+"$"); } könnte für ihn etwas wiederverwendbarer sein.

1 Stimmen

Diese Regex.escape Implementierung ist ziemlich übertrieben. Erstens verhindert das Vorkommen von arguments.callee einige der Optimierungen in modernen Browsern (und ist in ES5-strict veraltet), daher ist es besser, es zu vermeiden, wenn möglich. Zweitens gibt es eine unnötige Zeichenmaskierung, wo stattdessen eine Zeichenklasse verwendet werden könnte. Hier ist eine kleinere (und wahrscheinlich schnellere) Version, die wir in Prototype.js verwenden - RegExp.escape = function(str) { return str.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); };

0 Stimmen

Im SQL passt LIKE 'examp%' zu "example", passt jedoch nicht zu "an example" (siehe w3schools.com/SQL/sql_like.asp), während die obige Antwort beides passt. Eine Verbesserung für die zweite Zeile könnte sein: var match = new RegEx("^"+likeExpr.replace("%", ".*").replace("_", ".")+"$").exec(str) != null;

7voto

Steven de Salas Punkte 19903

Ich habe nach einer Antwort auf dieselbe Frage gesucht und bin nach dem Lesen von Kips Antwort darauf gekommen:

String.prototype.like = function(search) {
    if (typeof search !== 'string' || this === null) {return false; }
    // Sonderzeichen entfernen
    search = search.replace(new RegExp("([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])", "g"), "\\$1");
    // % und _ mit dem entsprechenden Regex ersetzen
    search = search.replace(/%/g, '.*').replace(/_/g, '.');
    // Überprüfen ob Übereinstimmungen vorhanden sind
    return RegExp('^' + search + '$', 'gi').test(this);
}

Sie können es dann wie folgt verwenden (beachten Sie, dass Groß-/Kleinschreibung ignoriert wird):

var url = 'http://www.mydomain.com/page1.aspx';
console.log(url.like('%mydomain.com/page_.asp%')); // true

HINWEIS 29.11.2013: Aktualisiert mit Leistungsverbesserung von RegExp.test() gemäß Lucios Kommentar unten.

0 Stimmen

Anstatt !!this.match(... zu verwenden, solltest du nicht lieber this.test(... verwenden?

1 Stimmen

Hallo @LucioM.Tato, die x.test() - Methode ist für RegExp-Instanzen und nicht für String-Objekte gedacht. http://www.w3schools.com/jsref/jsref_regexp_test.asp

0 Stimmen

Es tut mir leid, ich war nicht klar. Sie erhalten ein Übereinstimmungsarray (teurere RegExp) anstelle von .test (bessere Leistung) zu verwenden. Sollte sein: return new RegExp(...).test(this); anstatt einer doppelten Negation ein Array oder Null in ein Boolesches umzuwandeln. stackoverflow.com/questions/10940137/…

3voto

JohnLock Punkte 331

Eine alte Frage, aber es gibt hier tatsächlich keine guten Antworten. TSQL LIKE-Ausdrücke können eckige Klammern enthaltende Abschnitte enthalten, die bereits fast gültige reguläre Ausdrücke sind und das Übereinstimmen mit % und _ ermöglichen. Zum Beispiel:

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

Hier ist meine Funktion zum Umwandeln eines LIKE-Ausdrucks in einen RegExp. Die Eingabe wird in eckige Klammern und nicht eckige Klammern Abschnitte aufgeteilt. Die eckigen Klammern Abschnitte müssen nur mit Backslash escapen und die nicht eckigen Klammern Abschnitte sind vollständig escapet, während die Direktiven % und _ in reguläre Ausdrücke umgewandelt werden.

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');

2 Stimmen

Jeder, der nach einer Lösung sucht, um von der SQL LIKE-Syntax in einen JavaScript RegExp zu konvertieren, sollte so vorgehen. Es wird einen RegExp generieren, den Sie mit .test() usw. verwenden können.

2voto

Kip Punkte 102702

Hier ist eine Funktion, die ich verwende, basierend auf PHP's preg_quote Funktion:

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

Also wäre deine Zeile jetzt:

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

1voto

Joel Coehoorn Punkte 377088

Wenn Sie ein Regex verwenden möchten, können Sie jedes Zeichen der Zeichenfolge in eckige Klammern setzen. Dann müssen Sie nur wenige Zeichen maskieren.

Aber eine bessere Option könnte sein, die Zielsaiten abzuschneiden, sodass die Länge mit Ihrer Suchzeichenfolge übereinstimmt, und auf Gleichheit zu prüfen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X