L'espressione sembra buono nel complesso, come altri hanno detto, potrebbe essere un po 'prolisso con tutte le {0,1}
invece di ?
e (?:
invece di applicare RegexOptions.ExplicitCapture
. Ma questi non dovrebbero rendere l'espressione lenta. Risulteranno solo in una migliore leggibilità.
Ciò che potrebbe causare lentezza è il fatto che ci sono molte opzioni di backtracking nell'espressione facendo sia il mese espanso che il.opzionale. Mi chiedo cosa succederebbe se modificassi l'espressione per applicare solo l'opzionale. una volta, dopo il nome del mese, e che cosa accadrebbe se hai fatto il nome del mese un gruppo avido
In modo che ((?>pattern)
Nonbacktracking (o "avidi") subexpression.):
(jan(?:uary){0,1}\.{0,1}|feb(?:ruary){0,1}\.{0,1}|mar(?:ch){0,1}\.{0,1}|apr(?:il){0,1}\.{0,1}|may\.{0,1}|jun(?:e){0,1}\.{0,1}|jul(?:y){0,1}\.{0,1}|aug(?:ust){0,1}\.{0,1}|sep(?:tember){0,1}\.{0,1}|oct(?:ober){0,1}\.{0,1}|nov(?:ember){0,1}\.{0,1}|dec(?:ember){0,1}\.{0,1})\s+(\d{2,4}))
diventerebbero:
(?>jan(uary)?|feb(ruary)?|mar(ch)?|apr(il)?|may|june?|july?|aug(ust)?|sep(tember)?|oct(ober)?|nov(ember)?|dec(ember)?)\.?\s+(\d{2,4}))
Non solo è molto più breve, mi aspetterei che fosse più veloce.
E poi c'è la parte dell'espressione all'inizio, che per me non ha senso (?:(\d{1,4})- /.- /.)
O qualcosa si è perso nella formattazione, o questo non aiuta un po '.
\ d {1,4} avrebbe senso per un anno o qualsiasi altra parte di data, ma il - /.- /.
dopo non ha alcun senso. Penso che intendessi qualcosa del tipo:
\d{1,4}[- /.]\d{1,2}[- /.]\d{1,2}
O qualcosa in quella zona. Così com'è cattura immondizia, probabilmente non accelerando il processo di abbinamento.
Alla fine sono d'accordo con Aliostad, che probabilmente stai meglio cercando di trovare un modello meno preciso per trovare i candidati iniziali, quindi restringere i risultati utilizzando DateTime.TryParseExact o con un set aggiuntivo di espressioni.
Invece di creare un'espressione 'globale' per trovare i candidati, è possibile utilizzare un sacco di espressioni esatte. Vedrai che con Regex è spesso più economico eseguire un numero di espressioni esatte su un input di grandi dimensioni, piuttosto che eseguire un'espressione con un sacco di 's e?' S in là.
Così rompere la tua ricerca in molteplici espressioni molto precise potrebbe comportare una performance molto più alto, questi potrebbero essere un inizio:
\b\d{1,2}[- .\\/]\d{1,2}[- .\\/](\d{2}|\d{4})\b
\b((jan|feb|mar|apr|jun|jul|aug|sep|oct|nov|dec)(.|[a-z]{0,10})|\d{1,2})[- .\\/,]\d{1,2}[- .\\/,](\d{2}|\d{4})\b
Come si può vedere tutti i gruppi opzionali sono stati rimossi da queste espressioni, rendendo loro molto più veloce da eseguire. Ho anche rimosso l'esatta ortografia dai nomi dei mesi, poiché probabilmente vorrai accettare "sept" e "sep" nonché "settembre"
Rompere il pattern migliora anche la leggibilità :).
Un ultimo consiglio: limita la quantità di possibili caratteri di cui hai bisogno per tornare indietro, ponendo un limite su cose come \ s +, raramente vuoi abbinare 20.000 spazi, ma se sono nel tuo documento sorgente, proveranno abbinarli. \ s {1,20} è in genere sufficiente e limita la capacità del motore di cercare di ottenere una corrispondenza dove non ce n'è davvero una.
Un semplice commento, ma vorrei provare non regex uno per uno. Prima scansione con la prima espressione regolare ed eliminazione delle parole corrispondenti, quindi eseguire l'altra. Potrebbe essere più veloce a seconda della stringa di input. – daryal
'{0,1}' è uguale a '?'. Il cambiamento non accelera, ma semplifica la sua lettura per un po '. – kirilloid
Se si utilizza 'RegexOptions.ExplicitCapture', sarà un po 'più veloce e non sarà necessario utilizzare quei gruppi' (?:) '. –