2016-10-20 2 views
0

Wie erstellt man am besten einen dynamischen Regex, der einer bestimmten Menge von Zeichen (Zeichen und deren Reihenfolge zur Laufzeit) entspricht.Regex-Übereinstimmungszeichensatz ohne vorherige Duplizierung

character set: abcd 
character format: ??j? (question mark represents a a character from character set) 

Beispiel

abjd = match 
bdja = match 
dbja = match 
ab = no match 
aajd = no match 
abjdd = no match 
abj = no match 

ich einen regulären Ausdruck Builder erstellt haben (in js) wie folgt:

// characters are the character set 
// wordFormat is the character format 
// replace(str, search, replacement) replaces search in str with replacement 
var chars = "[" + characters + "]{1}"; 
var afterSpecialConversion = replace(wordFormat, "?", chars); 

var myRegex = new RegExp("^" + afterSpecialConversion + "$", "gi"); 

Leider ist dieses das Ergebnis nicht erreichen, da es nicht doppelte Elemente nicht berücksichtigt. Ich dachte über die Verwendung von übereinstimmenden Gruppen, um Duplikate zu vermeiden, aber ich weiß nicht, wie die bereits vorhandene Zeichengruppe aus dem Rest des Satzes zu negieren.

Auch gegebener Zeichensatz aabcd jetzt a kann zweimal existieren. Irgendwelche Vorschläge?

Antwort

1

Ihr Regex-Builder-Ansatz ist korrekt (obwohl ein bisschen eine Instandhaltungsmassage, so dokumentieren Sie es sorgfältig), aber nicht sehr anspruchsvoll genug. Was Sie tun müssen, ist lookaheads zu verwenden.

Ich habe eine example regex on Regex101 für die Demo in Ihrer Frage zur Verfügung gestellt.

Die allgemeinere Prinzip ist jeder Satz von n Fragezeichen mit einem Muster zu ersetzen, dies entspricht:

(?:([<chars>])(?!.*\<m>)){<n>} 

Wo <chars> wird der Zeichensatz, den Sie verwenden möchten, m ist der Index des Satzes von Fragezeichen (beginnend mit 1 - mehr dazu in einem Moment) und <n> ist die Anzahl der Fragezeichen in der Gruppe. Dies ergibt regex-Builder-Code, der wie folgt aussieht:

function getRe(pattern, chars) { 
    var re = "^"; 
    var qMarkGroup = 1; 
    var qMarkCount = 0; 

    for (var index in pattern) { 
     var char = pattern[index]; 
     if (char === "?") { 
      qMarkCount += 1; 
     } else { 
      if (qMarkCount > 0) { 
       re += "(?:([" + chars + "])(?!.*\\" + qMarkGroup + ")){" + qMarkCount + "}" + char; 
       qMarkCount = 0; 
       qMarkGroup += 1; 
      } 
     } 
    } 

    // Need to do this again in case we have a group of question marks at the end of the pattern 
    if (qMarkCount > 0) { 
     re += "(?:([" + chars + "])(?!.*\\" + qMarkGroup + ")){" + qMarkCount + "}"; 
    } 
    re += "$"; 
    return new Regexp(re, "gi"); 
} 

Code demo on Repl.it

Offensichtlich ist diese Funktionsdefinition ist sehr ausführlich, die Prinzipien zu demonstrieren. Fühlen Sie sich frei, es zu golf (aber denken Sie daran, für Fencepost Probleme wie ich in den Kommentaren beschrieben).

Stellen Sie außerdem sicher, dass die Eingänge bereinigt werden. Dies ist ein Beispiel und wird abgebrochen, wenn beispielsweise jemand ] in chars eingibt.

Verwandte Themen