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){ ... }

1voto

Rafi Punkte 707

Ich wollte etwas, das auch das Escapen der Platzhalter % und _ mit \% und \_ handhabt.

Hier ist meine Lösung mit negativem Lookbehind:

// escapes RegExp special characters
const escapePattern = s => s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');

// converts ILIKE pattern to a RegExp object
const ilikeToRegExp = pattern =>
  new RegExp(
    `^${escapePattern(pattern)}$`
      // convert ILIKE wildcards, don't match escaped
      .replace(/(?

`Verwendung:

ilikeToRegExp('%eLlo WoR%').test('hello world')  
// true

ilikeToRegExp('ello wor').test('hello world')  
// false

ilikeToRegExp('%90\%%').test('...90%...') 
// true`

0 Stimmen

Wenn Sie LIKE benötigen, entfernen Sie einfach das 'i' Flag.

0voto

Pramod Shivale Punkte 61

In der Antwort von Chris Van Opstal sollten Sie replaceAll anstelle von replace verwenden, um alle Vorkommen von '%' und '_' zu ersetzen. Verweis darauf, wie replaceAll durchgeführt wird - hier

0voto

richardwhitney Punkte 486

Johnny kommt hier zu spät, aber das funktioniert für mich. Ich benutze es für meine Spa-Seiten, um zu vermeiden, dass bestimmte Seiten nach der Standardseite Ergebnisse zeigen:

function like(haystack,needle){
    needle = needle.split(','); 
    var str = haystack.toLowerCase();
    var n = -1;
    for(var i=0;i -1){
            return n;
        }
    }
return n;
}

Die Verwendung ist - hier möchte ich keine Ergebnisse auf den Tools-, Kontakt- oder Startseiten anzeigen - results() ist eine Funktion, die ich hier nicht zeige:

var n = like($data,'tools,contact,home');
//~ alert(n);
if(n < 0){// stimmt mit nichts in dem obigen String überein
  results($data);
}

0voto

mishamosher Punkte 968

Ich brauchte das, mit Escaping und funktioniert in Safari (ohne negative Rückwärtsansichten). Hier ist, was ich entwickelt habe:

/**
 * Zitiert einen String gemäß den gleichen Regeln wie https://www.php.net/manual/function.preg-quote.php
 *
 * Bezogen von https://locutus.io/php/preg_quote/
 *
 * @param {string} str Zu zitierender String.
 * @param {?string} [delimiter] Delimiter, der ebenfalls zitiert wird.
 * @returns {string} Der zitierte String.
 */
function regexQuote(str, delimiter) {
    return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&');
}

/**
 * Entfernt die diakritischen Zeichen aus einem String.
 *
 * Diakritische Zeichen: {@link https://unicode-table.com/blocks/combining-diacritical-marks/}
 *
 * @param {string} str Der String, aus dem die diakritischen Zeichen entfernt werden sollen.
 * @returns {string} Bereinigter String.
 */
function stripDiacriticalMarks(str) {
    return unorm.nfkd(str).replaceAll(/[\u0300-\u036f]+/g, '');
}

/**
 * Überprüft, ob der String `haystack` wie `needle` ist, `needle` kann '%' und '_' enthalten
 * Zeichen, die sich verhalten, als ob sie in einem SQL LIKE-Bedingung verwendet würden. Zeicheneskapierung
 * wird mit '\' unterstützt.
 *
 * @param {string} haystack Der String, um zu überprüfen, ob er wie `needle` ist.
 * @param {string} needle Der String, mit dem überprüft wird, ob `haystack` ihm ähnlich ist.
 * @param {boolean} [ai] Ob Ähnlichkeit in einer akzentunempfindlichen Weise überprüft werden soll.
 * @param {boolean} [ci] Ob Ähnlichkeit in einer groß- und kleinschreibungsunempfindlichen Weise überprüft werden soll.
 * @returns {boolean} True, wenn `haystack` wie `needle` ist, ansonsten false.
 */
function strLike(haystack, needle, ai = true, ci = true) {
    if (ai) {
        haystack = stripDiacriticalMarks(haystack);
        needle = stripDiacriticalMarks(needle);
    }

    needle = regexQuote(needle, '/');

    let tokens = [];

    for (let i = 0; i < needle.length; ) {
        if (needle[i] === '\\') {
            i += 2;
            if (i < needle.length) {
                if (needle[i] === '\\') {
                    tokens.push('\\\\');
                    i += 2;
                } else {
                    tokens.push(needle[i]);
                    ++i;
                }
            } else {
                tokens.push('\\\\');
            }
        } else {
            switch (needle[i]) {
                case '_':
                    tokens.push('.')
                    break;
                case '%':
                    tokens.push('.*')
                    break;
                default:
                    tokens.push(needle[i]);
                    break;
            }
            ++i;
        }
    }

    return new RegExp(`^${tokens.join('')}$`, `u${ci ? 'i' : ''}`).test(haystack);
}

/**
 * Escapiert einen String so, dass `strLike` ihn entsprechend anpasst, sodass '%' und '_'
 * ein wörtliches '%' und '_' übereinstimmen würden (und sich nicht wie in einer SQL LIKE
 * Bedingung verhalten).
 *
 * @param {string} str Der zu escapierende String.
 * @returns {string} Der escapierter String.
 */
function escapeStrLike(str) {
    let tokens = [];

    for (let i = 0; i < str.length; i++) {
        switch (str[i]) {
            case '\\':
                tokens.push('\\\\');
                break;
            case '%':
                tokens.push('\\%')
                break;
            case '_':
                tokens.push('\\_')
                break;
            default:
                tokens.push(str[i]);
        }
    }

    return tokens.join('');
}

Der obige Code ist abhängig von unorm und ist unicode-fähig, um Fälle wie diese erkennen zu können:

strLike('Hallo ', 'Hallo _'); // true
strLike('Hallo ', '_e%o__');  // true
strLike('asdfas \\H\\\\%É\\l\\_\\l\\o asdfasf', '%' . escapeStrLike('\\h\\\\%e\\l\\_\\l\\o') . '%'); // true

0voto

pigeontoe Punkte 416

Ich habe schließlich eine Funktion geschrieben, die auf einigen Antworten hier basierte und für mich ziemlich gut funktioniert hat. Ich brauchte etwas, das die Syntax "startswith%" und "%endswith" beibehält und für eine leere Suchzeichenfolge keine Übereinstimmungen zurückgibt.

function sqlLIKE(target, likeExp) {
  let regex = likeExp
    .replaceAll(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1')
    .replaceAll("%", ".*")
    .replaceAll("_", ".");

  if (likeExp.charAt(0) !== '%' || !likeExp.includes('%')) regex = `^${regex}`;

  if (likeExp.charAt(likeExp.length - 1) !== '%' || !likeExp.includes('%')) regex = `${regex}$`;

  return new RegExp(regex).exec(target) !== null;
}

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