2016-02-24 19 views
6

Beispiel StringRegex eckigen Klammern bekommen nur Zahlen enthalten, aber sind nicht in eckigen Klammern selbst

"[] [ds*[000112]] [1448472995] sample string [1448472995] ***"; 

Die Regex

[1448472995] [1448472995] 

entsprechen sollte und [000112] nicht überein, da äußere Quadrat ist Klammer.

Zur Zeit habe ich diese Regex, die [000112] auch

const string unixTimeStampPattern = @"\[([0-9]+)]"; 
+0

Mit anderen Worten, Sie möchten eine Klammerzahl nur dann anpassen, wenn die gleiche Anzahl von (ausgeglichenen) öffnenden und schließenden Klammern folgt? –

+0

Sie müssen ausgeglichene Textregex verwenden, um verschachtelte Klammern auszuschließen. – sln

+1

@Tim: Ja, du hast Recht. – Sameer

Antwort

4

Dies ist ein guter Weg, um es mit ausgewogenem Text zu tun.

(\[ \d+ \])     # (1) 
|        # or, 
    \[       # Opening bracket 
    (?>       # Then either match (possessively): 
     [^\[\]]+      # non - brackets 
     |        # or 
     \[       # [ increase the bracket counter 
     (?<Depth>) 
     |        # or 
     \]       # ] decrease the bracket counter 
     (?<-Depth>) 
    )*       # Repeat as needed. 
    (?(Depth)      # Assert that the bracket counter is at zero 
     (?!) 
    ) 
    \]       # Closing bracket 

C# Probe

string sTestSample = "[] [ds*[000112]] [1448472995] sample string [1448472995] ***"; 
Regex RxBracket = new Regex(@"(\[\d+\])|\[(?>[^\[\]]+|\[(?<Depth>)|\](?<-Depth>))*(?(Depth)(?!))\]"); 

Match bracketMatch = RxBracket.Match(sTestSample); 
while (bracketMatch.Success) 
{ 
    if (bracketMatch.Groups[1].Success) 
     Console.WriteLine("{0}", bracketMatch); 
    bracketMatch = bracketMatch.NextMatch(); 
} 

Ausgabe

[1448472995] 
[1448472995] 
+0

Dieser ist viel Los performant im Vergleich zu Tims Lösung. Vielen Dank!!! – Sameer

-2

Dies wird Ihr Ausdruck entsprechen wie erwartet passend: http://regexr.com/3csg3 es Look-Ahead verwendet.

+2

Erstens, bitte posten Sie keine Antworten, die nur auf externe Seiten verlinken. Zweitens schlägt Ihre Regex fehl, sobald die zweite schließende Klammer nicht unmittelbar der ersten folgt, wie in '[foo [1234] bar]'. –

4

Sie müssen balancing groups verwenden, um dies zu handhaben - es ist ein bisschen einschüchternd aussieht, aber nicht alles, was kompliziert:

Regex regexObj = new Regex(
    @"\[    # Match opening bracket. 
    \d+    # Match a number. 
    \]     # Match closing bracket. 
    (?=    # Assert that the following can be matched ahead: 
    (?>    # The following group (made atomic to avoid backtracking): 
     [^\[\]]+   # One or more characters except brackets 
    |     # or 
     \[ (?<Depth>) # an opening bracket (increase bracket counter) 
    |     # or 
     \] (?<-Depth>) # a closing bracket (decrease bracket counter, can't go below 0). 
    )*    # Repeat ad libitum. 
    (?(Depth)(?!)) # Assert that the bracket counter is now zero. 
    [^\[\]]*   # Match any remaining non-bracket characters 
    \z    # until the end of the string. 
    )     # End of lookahead.", 
    RegexOptions.IgnorePatternWhitespace); 
+1

Dies dauert eine unerschwingliche Zeit, wenn Klammern immer nach dem '[\ d +]' validiert werden. Sie können dies testen, indem Sie Kopien der Testzeichenfolge verketten. Ich habe 2000 Kopien gemacht, habe 5 Minuten gewartet, es kam nie zurück. Meins kam in 1 Sekunde zurück. Es ist wahrscheinlich schneller, vor der Zeit getrennte Klammern an der Saite separat zu validieren. Dann mache einen einfachen Wechsel. – sln

+0

@Tim: Danke !!! das war hilfreich. Ich versuche, mit der Parsing-Logik fertig zu werden :). Ich brauche eckige Klammern in einer Übereinstimmung und Nummer als eine Gruppe der Übereinstimmung, da meine Übereinstimmung durch DateTime ersetzt werden sollte, das von unixTime abgeleitet wird. Ich könnte die öffnende Klammer anpassen, indem ich einfach (? <= \ [) Dies durch \] ersetze, aber nicht herausfinden konnte, wie ich den schließenden Strich treffen soll. – Sameer

0

Sind Sie nur die Unix-Zeitstempel zu erfassen versuchen? Dann können Sie einen einfacheren versuchen, bei dem Sie die Mindestanzahl von Zeichen angeben, die in einer Gruppe übereinstimmen.

\[([0-9]{10})\] 

Hier beschränke ich es bis zu 10 Zeichen, da ich die Zeitstempel zweifeln 11 Zeichen treffen wird in absehbarer Zeit ... gegen das schützen:

\[([0-9]{10,11})\] 

Natürlich, dies zu falschen Positiven führen könnte, wenn Sie haben eine 10-lange Zahl in einer umschließenden Klammer.

Verwandte Themen