Tengo una cadena de búsqueda ingresada por un usuario. Normalmente, la cadena de búsqueda se divide utilizando espacios en blanco y luego se realiza una búsqueda OR (un elemento coincide si coincide con cualquiera de los elementos de la cadena de búsqueda). Deseo proporcionar algunas características de consulta "avanzadas", como la posibilidad de utilizar comillas para encerrar frases literales que contengan espacios en blanco.Regex tomando un tiempo sorprendentemente largo
Pensé que había creado una expresión regular decente para separar las cuerdas, pero me tomó un tiempo sorprendentemente largo en la ejecución (> 2 segundos en mi máquina). Lo encontré para averiguar dónde estaba el problema, y lo que es más interesante parece que ocurre después de que coincida el último Match
(presumiblemente, al final de la entrada). Todas las coincidencias hasta el final de la cadena coinciden en menos tiempo que luego puedo capturar, pero esa última coincidencia (si eso es lo que es, nada vuelve) toma casi todos los 2 segundos.
Esperaba que alguien pudiera tener alguna idea de cómo puedo acelerar esta expresión regular un poco. Sé que estoy usando un vistazo con un cuantificador ilimitado pero, como dije, esto no parece causar ningún problema de rendimiento hasta después de que se haya emparejado el último partido.
CÓDIGO
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace RegexSandboxCSharp {
class Program {
static void Main(string[] args) {
string l_input1 = "# one \"two three\" four five:\"six seven\" eight \"nine ten\"";
string l_pattern =
@"(?<=^([^""]*([""][^""]*[""])?)*)\s+";
Regex l_regex = new Regex(l_pattern);
MatchCollection l_matches = l_regex.Matches(l_input1);
System.Collections.IEnumerator l_matchEnumerator = l_matches.GetEnumerator();
DateTime l_listStart = DateTime.Now;
List<string> l_elements = new List<string>();
int l_previousIndex = 0;
int l_previousLength = 0;
// The final MoveNext(), which returns false, takes 2 seconds.
while (l_matchEnumerator.MoveNext()) {
Match l_match = (Match) l_matchEnumerator.Current;
int l_start = l_previousIndex + l_previousLength;
int l_length = l_match.Index - l_start;
l_elements.Add(l_input1.Substring(l_start, l_length));
l_previousIndex = l_match.Index;
l_previousLength = l_match.Length;
}
Console.WriteLine("List Composition Time: " + (DateTime.Now - l_listStart).TotalMilliseconds.ToString());
string[] l_terms = l_elements.ToArray();
Console.WriteLine(String.Join("\n", l_terms));
Console.ReadKey(true);
}
}
}
SALIDA
(Esto es exactamente lo que estoy haciendo.)
uno
"dos tres "
cuatro
cinco:" seis siete"
ocho
"nueve diez"
¿Se puede escribir la expresión regular sin mirar hacia atrás de longitud variable? Ese probablemente es el problema. O simplemente escribe un analizador simple en lugar de regex. – nhahtdh
Había considerado un analizador sintáctico, pero la expresión regular parecía más simple. Todo lo que necesito hacer es dividir el texto en fragmentos, teniendo en cuenta las citas. Y la expresión regular va como dickens hasta ese último MoveNext() - ese es el único lugar que toma 2 segundos. – JDB
Agradecería los comentarios de los downvoters sobre cómo se puede mejorar esta pregunta. – JDB