46 Stimmen

Regex.test() funktioniert nur jedes zweite Mal.

Regex test() bereitet mir Probleme in Firefox und Chrome, funktioniert jedoch einwandfrei in Opera und Safari.

Problembereiter Code:

var pattern = /(\s+(?!\$\w+)|(^(?!\$\w+)))/g;
if(pattern.test(String(id).replace(/\s+OR|AND\s+/g, ''))) {
 searchError("Du bist schlecht.");
 return 1;
}

Wenn Sie Leerzeichen übergeben, blockiert es diese jedes Mal. Wenn Sie etwas wie '$a b' übergeben, funktioniert es dann jeden zweiten Mal in Firefox/Chrome. KOMISCH.

0 Stimmen

Ersetzen Sie id durch etwas Statisches und sehen Sie, ob es funktioniert.

1 Stimmen

Omg :-) scheint ein lustiger Fehler zu sein ...

97voto

Nick Craver Punkte 609016

Es handelt sich um einen Fehler im RegEx-Engine, hier kam eine ähnliche Frage mit dem gleichen Problem auf.

Aus meiner Antwort auf diese Frage: Es handelt sich um einen Fehler in der Art und Weise, wie Regexes in ECMAScript 3 implementiert sind, hier gibt es einen großartigen Beitrag zu den Details.

Die Grundlagen sind ein /regex/ mit dem Modifier g wird nicht richtig zurückgesetzt, daher wechseln mehrere .test()-Aufrufe zwischen true und false, wenn eigentlich alle true sein sollten, jede zweite erfolgreiches Aufrufen setzt es zurück.

0 Stimmen

Oh verdammt. Ihr seid super. Vielen Dank für die schnellen Antworten und hilfreichen Links (das war schwierig, Lösungen dafür zu finden).

1 Stimmen

@Jackson, wenn diese Antwort deine Frage beantwortet (was sie sollte), dann klicke auf das kleine Häkchen links - um sie als die akzeptierte Antwort zu markieren.

0 Stimmen

@Brock Adams Das muss mir entgangen sein. Danke für die Erinnerung.

6voto

Willie Punkte 139

Aktualisierung: 27.9.23 - Ich stoße IMMER NOCH auf dieses Problem.

Betrachten Sie das Folgende:

  1. Sie verwenden Angular reaktive Formen und nutzen einige integrierte Funktionen wie die vorgefertigten Validatoren.
  2. Sie verwenden etwas Ähnliches wie das Folgende.

      form.forEach((formField: any) => {
        let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
          switch(validator.type){
            case 'required':
              validators.push(Validators.required);
              break;
            case 'pattern':
              validators.push(Validators.pattern(new RegExp(validator.value)));
              break;

wobei jeder Validator ein von mir auf unserem Server definiertes Objekt ist, wie z.B.:

{
"name": "kleinschreibungundunterstrich"
"value": "^[a-z_]*$",
"type": "pattern",
"error": "Spaltennamen dürfen nur Kleinbuchstaben und Unterstriche enthalten"
}

Man könnte annehmen, dass dies grundsätzlich mit reaktiven Formen funktionieren würde, aber das tut es nicht! Es fällt in dasselbe Loch wie der Beitrag von 2021 unten. Lass dich nicht täuschen!

Ich bin heute auf Folgendes gestoßen.

Merkwürdigerweise funktioniert folgendes:

      form.forEach((formField: any) => {
        let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
          switch(validator.type){
            case 'required':
              validators.push(Validators.required);
              break;
            case 'pattern':
              validators.push(Validators.pattern(new RegExp(/^[a-z_]*$/)));
              break;

Dies scheitert nicht jedes zweite Mal!

Aber wenn Sie eine Regex erstellen, die aus einer KLASSE stammt, indem Sie einen STRING verwenden... seien Sie vorsichtig. Sie müssen etwas wie das Folgende tun.

      form.forEach((formField: any) => {
        let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
          switch(validator.type){
            case 'required':
              validators.push(Validators.required);
              break;
            case 'pattern':
              validators.push(this.testValue(validator));
              break;

wobei Ihre testValue-Funktion folgendermaßen aussieht:

private testValue(validator: any): ValidatorFn {
    return (control: AbstractControl) => {
      let returnVal = null;
      if(control.value){
        //BEMERKEN Sie die Verwendung von Klammern um die RegExp unten.
        if((new RegExp(validator.value, 'gm').test(control.value))){
          return null;
        } else {
          return {[validator.name]: validator.error};
        }
      }
      return returnVal;
    }
  }

Als ich heute daran gearbeitet habe, dachte ich ehrlich gesagt "sicher kann ich nicht dasselbe Problem mit Regexen haben...". Es stellte sich heraus, dass ich es hatte.

Es gibt etwas zu sagen jedes Mal, wenn Sie eine RegExp mit einem String erstellen. Wickeln Sie ihn einfach in Klammern. Aus irgendeinem Grund funktioniert es wie es sollte, wenn Sie es ohne ein Stringliteral erstellen.

Ich hoffe, das verdeutlicht diesen Punkt.

Im Grunde genommen verhalten sich Regexe anscheinend falsch, wenn sie aus Zeichenfolgenliteralen erstellt werden, und funktionieren scheinbar einwandfrei, wenn sie NICHT aus einer Zeichenfolge erstellt werden.

///Ende des Updates

Dies scheint immer noch ein Problem im August 2021 zu sein... Ich möchte nur einige Dinge teilen, die ich gelernt habe, bevor ich auf diese Frage und Antwort gestoßen bin. Ich war von diesem Problem verwirrt und hatte keinen sinnvollen Weg nach vorne - bis jetzt.

  1. Es spielt keine Rolle, ob Sie exec() oder test() oder match() verwenden. Die Regex funktioniert immer noch nicht richtig bei jedem zweiten Auftreten.

  2. Es spielt keine Rolle, ob Sie die Regex mit

    let reg = new RegExp(/]*)>/g);

oder mit const festlegen. Es spielt auch keine Rolle, ob Sie sie global oder lokal festlegen...

Was wohl daran vorbeiführt, dieses Problem zu umgehen, ist das Einhüllen Ihrer Regex-Anweisung in Klammern in Ihrer Schleife, wie folgt:

Object.keys(table).forEach(key => {
    if((new RegExp(/]*)>/g)).test(___Ihr Teststring___)){
        //Tun Sie, was Sie tun müssen
    }
});

Entfernen Sie die Klammern um die Regex, und beobachten Sie, wie jede andere fehlschlägt....

Vielen Dank für die Antwort @Nick Craver und den Kommentar @prototype!

Diese genaue Regex hat mir Probleme bereitet. Es hat für ein Objekt funktioniert und für das nachfolgende Objekt versagt, und das ergibt keinen Sinn. Ich bin nur hier, um zu sagen, dass dies auch 2021 sehr relevant ist.

1 Stimmen

Schau mal @halfer, ich schätze die Bearbeitung, aber ich schätze es nicht, dass "Gott sei Dank" entfernt wurde. Ernsthaft, ich konnte tagelang keine Antwort finden und habe schließlich diese bereits gepostete Antwort gefunden. Wenn Dinge wie diese manchmal keine Geschenke Gottes sind, dann weiß ich nicht, was ist... Ich würde diese "Antwort" lieber einfach löschen (was wirklich nur das Problem der Regex-Verbreitung auf andere Bereiche zeigt), wenn du Gott daraus entfernen willst.

0 Stimmen

Ich verstehe deine Ansicht und sympathisiere. Über die Jahre hinweg hatten wir hier einige Leute, die theistisches, religiöses, abergläubisches und ähnliches Material zu ihren Beiträgen hinzufügen wollten, und die allgemeine Meinung der Community ist, dass dies nicht die technische, neutrale Sichtweise repräsentiert, die wir anstreben. Wir haben eine kanonische Diskussion hier.

0 Stimmen

Das Ding mit Stack Overflow ist, dass wir sozusagen Dokumentation für viele zukünftige Leser erstellen, und das kann für neue Mitglieder überraschend sein. Ich erkenne an, dass es eine Weile dauert, sich daran zu gewöhnen, da das "Forenmodell" dazu führte, dass Beitragende Beiträge als ihr eigenes Material betrachten (über das sie die volle Kontrolle ausüben konnten). Wir sind hier vielleicht eher wie ein gemeinsam bearbeitbares Wiki.

0voto

shieldgenerator7 Punkte 1237

Für irgendeinen Grund funktioniert matchAll() richtig, auch wenn test() nicht funktioniert.

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