2016-02-24 18 views
6

String EsempioRegex per ottenere le parentesi quadre contengono solo numeri, ma non sono tra parentesi quadre si

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

l'espressione regolare deve corrispondere

[1448472995] [1448472995] 

e non deve corrispondere [000112] poiché non v'è piazza esterna staffa.

Attualmente ho questo regex che è la corrispondenza [000112] così

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

In altre parole, si desidera abbinare un numero tra parentesi solo se segue lo stesso numero di parentesi di apertura e chiusura (bilanciate)? –

+0

È necessario utilizzare espressioni regolari di testo bilanciate per escludere parentesi nidificate. – sln

+1

@ Tim: Sì, hai ragione. – Sameer

risposta

4

Questo è un buon modo per farlo utilizzando testo equilibrato.

(\[ \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# campione

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(); 
} 

uscita

[1448472995] 
[1448472995] 
+0

Questo è molto più performante rispetto al soln di Tim. Grazie!!! – Sameer

-2

Questa abbinerà la tua espressione come previsto: http://regexr.com/3csg3 utilizza lookahead.

+2

Innanzitutto, non pubblicare risposte che collegano solo a siti esterni. In secondo luogo, la regex non riesce non appena la seconda parentesi di chiusura non segue immediatamente la prima, come in '[foo [1234] bar]'. –

4

è necessario utilizzare balancing groups per gestire questo - sembra un po 'scoraggiante, ma non è poi così complicato:

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

Questo richiede un tempo proibitamente lungo quando convalida le parentesi oltre il '[\ d +]' ogni volta. Puoi testare questo catenando copie della stringa di test. Ho fatto 2000 copie, ho aspettato 5 minuti, non è mai tornato. Il mio è tornato in 1 secondo. Probabilmente è più veloce convalidare le parentesi equilibrate sulla stringa separatamente, in anticipo. Quindi fai una semplice alternanza. – sln

+0

@Tim: Grazie !!! è stato utile. Sto cercando di far fronte alla logica dell'analisi :). Ho bisogno di ottenere parentesi quadre in una partita e il numero come un gruppo della partita, Dal momento che la mia partita dovrebbe essere sostituita da DateTime derivato da unixTime. Potrei abbinare la parentesi di apertura semplicemente (? <= \ [) Sostituendo questo con \] ma non riuscivo a capire come abbinare il bracet di chiusura. – Sameer

0

Stai solo cercando di catturare l'UNIX timestamp? Quindi puoi provare uno più semplice in cui specifichi il numero minimo di caratteri abbinati in un gruppo.

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

Qui ho limitarla a 10 caratteri in quanto dubito il timestamp colpirà 11 caratteri in qualunque momento presto ... Per evitare che:

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

Naturalmente questo potrebbe portare ad un falso allarme Se hai un numero di 10 lunghezza in una parentesi chiusa.

Problemi correlati