Domanda

Consideriamo le due seguenti righe in C # (usando framework .NET 3.5)

Regex regex = new Regex(@"^((E|e)t )?(M|m)oi (?<NewName>[A-Za-z]\.?\w*((\-|\s)?[A-Za-z]?\w{1,})+)<*>quot;, RegexOptions.Compiled | RegexOptions.IgnoreCase);
Match m = regex.Match("moi aussi jaimerai etre un ordinateur pour pas m'énnerver ");

(scusate se è un programma francese :))

Quando vengono eseguiti, il processo si blocca nel metodo Match () e non termina mai. Immagino che ci sia qualche problema con lo spazio bianco nel pattern regex ma quello che vorrei fare non è cambiare il pattern (in realtà è impostato fuori dal programma, dagli utenti finali del mio strumento) ma essere in grado di interrompere il processo (con un timeout per esempio).

Qualcuno sa se questo è un problema ben noto con .NET Regular Expression e se esiste un modo semplice per aggirare il problema o devo infilare queste righe e interromperle se necessario (sicuramente non mi piacerebbe per farlo).

È stato utile?

Soluzione

Penso che dovresti semplicemente lanciare la partita Regex su un thread separato e consentire che venga interrotta se viene raggiunto un certo limite di tempo massimo.

Altri suggerimenti

Se inserisco l'espressione in Regexbuddy, presenta il seguente messaggio

  

Il tentativo di incontro è stato interrotto in anticipo   perché anche l'espressione regolare   complesso. Il motore regex che prevedi   usarlo con potrebbe non essere in grado di gestirlo   tutto e crash. Consultare   "backtracking catastrofico" nel   file di aiuto per imparare come evitarlo   situazione.

Cercare backtracking catastrofico fornisce la seguente spiegazione

  

Espressioni regolari in fuga: catastrofico backtracking
  Considera l'espressione regolare (x + x +) + y.   Prima di urlare di orrore e dire   questo esempio inventato dovrebbe essere   scritto come xx + y per corrispondere esattamente a   lo stesso senza quelli terribilmente nidificati   quantificatori: supponi solo che ciascuno di "quot" x "   rappresenta qualcosa di più complesso,   con determinate stringhe corrispondenti   entrambi " x " ;. Vedi la sezione su HTML   file di seguito per un esempio reale.

     

Vediamo cosa succede quando si applica   questa regex a xxxxxxxxxxy. Il primo   x + corrisponderà a tutti i 10 caratteri x. Il   il secondo x + fallisce. Il primo x + quindi   torna a 9 partite e il   il secondo raccoglie la rimanente x.   Il gruppo ora ha abbinato una volta. Il   il gruppo si ripete, ma all'inizio fallisce   x +. Dal momento che una ripetizione era   sufficiente, il gruppo corrisponde. y   corrisponde a y e una corrispondenza generale è   trovato. La regex è dichiarata   funzionale, il codice viene spedito al   cliente e il suo computer esplode.   Quasi.

     

Il regex sopra diventa brutto quando y   manca dalla stringa dell'oggetto.   Quando y fallisce, il motore regex   marcia indietro. Il gruppo ne ha uno   iterazione in cui può tornare indietro. Il   la seconda x + corrisponde a una sola x, quindi   non posso tornare indietro. Ma il primo x + può   rinunciare a una x. Il secondo x + prontamente   corrisponde a xx. Il gruppo ha di nuovo uno   iterazione, fallisce il prossimo e il   y fallisce. Backtracking di nuovo, il   il secondo x + ora ha un backtracking   posizione, riducendo se stesso per abbinare x.   Il gruppo tenta una seconda iterazione.   Il primo x + corrisponde ma il secondo è   bloccato alla fine della corda.   Backtracking di nuovo, il primo x + in   la prima iterazione del gruppo si riduce   stesso a 7 caratteri. Il secondo x +   corrisponde a xxx. In mancanza di y, il secondo x +   viene ridotto a xx e quindi x. Ora il   il gruppo può corrispondere a una seconda iterazione,   con una x per ogni x +. Ma questo   Anche la combinazione (7,1), (1,1) fallisce. Così   va a (6,4) e poi (6,2) (1,1)   e poi (6,1), (2,1) e poi   (6,1), (1,2) e poi penso che inizi   per ottenere la deriva.

     

Se provi questo regex su una stringa 10x   nel debugger di RegexBuddy, ci vorrà   2558 passi per capire l'ultimo y   manca. Per una stringa 11x, esso   ha bisogno di 5118 passaggi. Per 12, ci vuole   10238 passi. Chiaramente abbiamo un   complessità esponenziale di O (2 ^ n) qui.   A 21x il debugger si inchina a 2.8   milioni di passi, diagnosticare un brutto caso   di backtracking catastrofico.

     

RegexBuddy sta perdonando in questo   rileva che sta andando in cerchio e   interrompe il tentativo di incontro. Altra regex   i motori (come .NET) continueranno a funzionare   per sempre , mentre altri andranno in crash   uno stack overflow (come Perl, prima   versione 5.10). Gli overflow dello stack sono   particolarmente brutto su Windows, da allora   tendono a fare la tua domanda   svanire senza lasciare traccia o spiegazione.   Fai molta attenzione se gestisci un web   servizio che consente agli utenti di fornire   le loro espressioni regolari. Persone   con poca esperienza regex hanno   abilità sorprendente a venire con   regolare esponenzialmente complesso   espressioni.

Suppongo che dovrai gestirlo nel codice. Ti suggerirei di contattare l'autore di Regexbuddy e chiedere cosa è necessario per rilevare questo scenario.

In generale, le espressioni regolari possono richiedere più tempo del previsto. Dovresti sperimentare l'espressione regolare hjusing uno strumento come Regulator.

Il problema è che hai annidato " loop " nel tuo Regex, che lo rende terribilmente inefficiente (in modo che in pratica richieda per sempre a causa della complessità dell'espressione).

Se dici quello che vorresti abbinare, posso provare a trovare un Regex più efficiente per quello.

Mi sembra un caso il match di regex che cresce in modo esponenziale. Vedi il blog BCL .

La soluzione migliore è impostare un timeout sul regex, senza fare confusione con i thread.

Vedi qui come rimuovere le stringhe con timeout .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top