2017-07-06 5 views
1

Benutzereingabe Format:Pattern Matching - Regex

[fieldname1] Komparator [fieldvalue1, fieldvalue2, value3], [FieldName2] Komparator [fieldvalue1, Wert2, ..] ..

Notwendigkeit, diese in analysieren:

1. [fieldname1] Komparator [fieldvalue1, fieldva lue2, value3]

2. [FieldName2] Komparator [fieldvalue1, Wert2, ..] und so weiter

(ie) jedes Feld zusammen mit seinem Komparator und Wert getrennt werden. während Komparator wird irgendeine der unten:

< = |> = | = | is | < |> | startswith | Beginnt mit | Beginnt mit | Beginnt mit | Beendet mit | Endswith |

enthält

Regex von mir verwendet:

([.?() +] (\ S) (< = |> = | = | is | < | > | starts | Startet mit | Beginswith | Beginnt mit | kurz mit | EndsWith | enthält) (\ s) [() +.?] (\) *)

Beispiel: [firma] enthält [abc, efg], [email] enthält [cdf, test] oben wird ordnungsgemäß keine Probleme geparst.

Problem: Wenn Feldnamen oder Feldwert enthält Symbol "[" oder "]" das Parsen schief geht.

Beispiel: [Firma] enthält [ab [] c, efg], [E-Mail] enthält [siva, test]

Above gültig ist, aber da [] verwendet wird, als Begrenzer es Parsen stoppt bis [Unternehmen] enthält [ab [], aber ich es richtig, wie oben zum Beispiel analysieren möchten,

1. [Firma] enthält [ab [] c, efg]

2. [email] [siva enthält, Test]

Danke.

+1

Welche Sprache/Werkzeug benutzen Sie? Ich bin mir nicht sicher, ob Sie die gewünschte Nummerierung mit pure regex erhalten können. –

+0

Sprache ist JAVA – Naksh17

Antwort

0

Sie können mit dieser Regex versuchen:

,(?=(?:(?:[^\\[\\]]*[\\]\\[]){2})*[^\\[\\]]*$) 

Ihre Zielstring Splitting sollten Sie die Liste von gespaltet Ergebnismenge geben.Über die Sie Ihren Vergleicher leicht anpassen können

Mit diesem erhalten Sie die ausgeführte Ergebnis. Alles, was Sie überprüfen müssen, ist, ob jeder Index den richtigen Vergleicher enthält, wie Sie gezeigt haben. Wenn nicht, dann entferne das aus dem Array.

Die oben genannten Code-Ausgänge:

[ 
    [company] contains [ab[]c,efg], 
    [email] contains [siva,test] 
] 

Regex101Demo

Erläuterung:

Wann immer ein, gefunden wird ->

,(?=(?:(?:[^\\[\\]]*[\\]\\[]){2})*[^\\[\\]]*$) 

ein p ositive Vorschau läuft bis zum Ende der Zeichenkette wo die folgende Zeile

(?:[^\\[\\]]*[\\]\\[]){2})* stellt sicher, dass - wenn eine Klammer gefunden wird, wird es zweimal gefunden. Dann zeigt das letzte * 0 oder mehr Wiederholungen des Klammerpaares an.

Warum ist das wichtig? Von jedem Komma, und danach zählt man die Anzahl der [und] Klammern. Und Sie werden sehen, dass Sie nur durch dieses Komma trennen müssen, wenn nur die Anzahl der Klammern dahinter steht. und Sie möchten nicht für Kommas trennen, für die eine ungerade Anzahl von Klammern danach kommt. Das ist die Erklärung.

Für die vollständige Gliederung der Regex können Sie in den Link schauen, wo im oberen rechten Abschnitt die vollständige Erklärung Zeichen für Zeichen gegeben wird.

+0

Danke! können Sie bitte die Regex erklären, die Sie erwähnt haben. ** existierender Code **: 'Muster p = Pattern.compile (criteriaRegEx, Pattern.CASE_INSENSITIVE); \t \t \t \t int crtCount = 0; \t \t \t \t Matcher m = p.matcher (Kriterien); \t \t \t \t Zeichenfolge [] criteriaArr = new String [100]; \t \t \t \t int Start = 0, Ende = 0; \t \t \t \t \t \t \t \t while (m.find()) {\t \t \t \t \t \t \t start = m.start (0); \t \t \t \t \t Ende = m.end (0); \t \t \t \t \t Zeichenfolge temp = criteriaSubstring (Anfang, Ende); \t \t \t \t \t kriterienArr [crtCount] = temp; \t \t \t \t \t crtCount ++; ' ** ** Dank – Naksh17

+0

@Siva Ich habe eine Erklärung gegeben. –

+0

Vielen Dank. Es hat gut funktioniert! und ich angewendet \t \t \t \t \t 'String nameValRegex =„(i?) (<=|> = | = | ist | <|> | starts | Beginnt mit | Beginswith | Beginnt mit | Endet mit | EndsWith | enthält)? (= (?: (?: [^ \\ [\\]] * [\\] \\ []) {2}) * [^ \ [\\]] * $) ";' diese Regex zum Trennen des Komparators, Feld Name und Wert.Wenn es einen besseren Weg gibt, schlagen Sie bitte vor. * danke Rizwan *! – Naksh17

0

Also im Grunde müssen Sie die Zeichenfolge bei jedem , teilen, die zwischen ] und [ ist.

Wenn Sie Googles Guave verwenden, können Sie die Splitter und Split auf einer Regex mit positve lookbefore ] und positive Lookbehind verwenden [

String s = "[fieldname1] comparator [fieldvalue1,fieldvalue2,value3],[fieldname2] comparator [fieldvalue1,value2]"; 
Pattern stringPattern = Pattern.compile("(?<=\\]),(?=\\[)"); 
Iterable<String> split = Splitter.on(stringPattern).omitEmptyStrings().split(s); 
split.forEach(System.out::println); 
0

Zuerst müssen wir einen regulären Ausdruck definieren, der den Namen übereinstimmt, eine andere, die den Komparator entspricht, und einen dritten, der einen Wert übereinstimmt:

private static final String NAME_RE = "[A-Za-z0-9_]+"; 
private static final String VALUE_RE = "[A-Za-z0-9_\\[\\]\\.]+"; 
private static final String COMPARATOR_RE 
     = "<=|>=|=|is|<|>|startswith|Starts with|Beginswith|Begins with|Ends with|Endswith|Contains"; 

Wir können nun das Muster erstellen, die diese Unter regexps kombiniert:

private static final String RE = "\\s*\\[(" + NAME_RE + ")\\]\\s*" 
     + "(" + COMPARATOR_RE + ")\\s*\\[\\s*(" 
     + VALUE_RE + "(?:\\s*,\\s*" + VALUE_RE + ")*)\\s*\\]" 
     + "(?:\\s*,\\s*(.*))?"; 
private static final Pattern PATTERN 
     = Pattern.compile(RE, Pattern.CASE_INSENSITIVE); 

Beachten Sie, dass es mit einer einzelnen Regel übereinstimmt, die möglicherweise von einem Komma und den anderen Regeln gefolgt wird.

Die Analyse eines Quellzeichenfolge müssen die Regeln durchlaufen:

private static void parse(String source) { 
    String s = source; 
    while (s != null) { 
     Matcher matcher = PATTERN.matcher(s); 
     if (!matcher.matches()) { 
      throw new IllegalArgumentException("Invalid syntax: " + source); 
     } 
     String name = matcher.group(1); 
     String comparator = matcher.group(2); 
     String values = matcher.group(3); 
     s = matcher.group(4); 
     System.out.println("[" + name + "] " + comparator + " [" + values + "]"); 
    } 
} 

Nun wollen wir versuchen, Ihre zwei Beispiele zu analysieren:

private static final String EXAMPLE1 = "[company] contains [abc,efg],[email] contains [cdf,test]"; 
private static final String EXAMPLE2 = "[company] contains [ab[]c,efg],[email] contains [siva,test]"; 

public static void main(String[] args) { 
    parse(EXAMPLE1); 
    parse(EXAMPLE2); 
} 

Es wird die folgende Ausgabe erzeugt:

[company] contains [abc,efg] 
[email] contains [cdf,test] 
[company] contains [ab[]c,efg] 
[email] contains [siva,test] 

UPDATE:

Beachten Sie, dass der Inhalt eines Werts eingeschränkt werden muss, da, wenn "efg]" und "[email] enthält [cdf" beide akzeptabler Wert sind, es keine Möglichkeit gibt zu wissen, ob diese Beispiele aus ein oder zwei Regeln bestehen.

UPDATE 2:

Hier ist eine ziemlich lose regexp für VALUE_RE:

private static final String VALUE_RE 
     = "[^,\\[\\]]*(?:\\[[^,\\[\\]]*\\][^,\\[\\]]*)*"; 

hier ein Wert jedes Komma nicht enthalten kann, und nur ausgeglichene Klammer, ohne Verschachtelung.

+0

Aber wenn ich versuche, andere Zeichen auf den Feldnamen hinzuzufügen, es gab einige Fehler 'private static final String NAME_RE verursacht =„[A-Za-z0-9 _ \\ [\\] \\ s ~ ! '@ # $%^& * \\ (\\) - \\ + '\ "\\ \\/\\\\\\ =] +.?"; ' ' private static final String EXAMPLE2 = "[Name] = [Test], [Fullname] = [te], [Wechselkurs] [1], [Dezimal 1] = [12], [Companynumber] <= [123457]"; '** Danke Maurice ** – Naksh17