У меня есть строка поиска, введенная пользователем. Обычно строка поиска разделяется с использованием пробелов, а затем выполняется поиск OR (элемент соответствует, если он соответствует любому элементу строки поиска). Я хочу предоставить несколько "расширенных" функций запроса, таких как возможность использования кавычек для включения буквенных фраз, содержащих пробельные символы.
Я, хотя я заработал приличное регулярное выражение, чтобы разделить строки для меня, но он занимает удивительно долгое время для выполнения ( > 2 секунды на моей машине). Я разбил его, чтобы выяснить, где именно была икота, и, что еще более интересно, похоже, что это происходит после того, как последний Match
соответствует (предположительно, в конце ввода). Все совпадения до конца строки соответствуют меньше времени, чем я могу захватить, но последнее совпадение (если это то, что оно есть - ничего не возвращает) занимает почти все 2 секунды.
Я надеялся, что у кого-то может быть некоторое представление о том, как я могу немного ускорить это регулярное выражение. Я знаю, что я использую lookbehind с неограниченным квантификатором, но, как я уже сказал, это не вызывает каких-либо проблем с производительностью до тех пор, пока не будет сопоставлено последнее совпадение.
КОД
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 );
}
}
}
OUTPUT
(Это именно то, что я получаю.)
один
"два три"
четыре
пять: "шесть семь"
восемь
"девять десять"