Я помню пример из учебника.Имейте в виду, что ни один из следующих подходов не рекомендуется для производственного использования!Вместо этого используйте правильный синтаксический анализ CSV.
Ошибка, сделанная в этом примере, довольно распространена: использование точки, где более узкий класс символов подходит лучше.
В файле CSV, содержащем в каждой строке точно12 целых чисел, разделенных запятыми, найдите строки с 13 в 6-й позиции (независимо от того, где еще может быть 13).
1, 2, 3, 4, 5, 6, 7, 8 ,9 ,10,11,12 -- don't match
42,12,13,12,32,13,14,43,56,31,78,10 -- match
42,12,13,12,32,14,13,43,56,31,78,10 -- don't match
Мы используем регулярное выражение, содержащее ровно 11 запятых:
".*,.*,.*,.*,.*,13,.*,.*,.*,.*,.*,.*"
Таким образом, каждое ". *" Ограничивается одним числом.Это регулярное выражение решает задачу, но имеет очень плохую производительность.(Примерно 600 микросекунд на строку на моем компьютере, с небольшой разницей между согласованными и несопоставленными строками.)
Простое решение без регулярных выражений состояло бы в split()
каждой строке и сравнении 6-го элемента.(Гораздо быстрее: 9 микросекунд на строку.)
Причина, по которой регулярное выражение является таким медленным, заключается в том, что квантор "*" по умолчанию жадный, и поэтому первый ". *" Пытается соответствовать всей строке,и после этого начинается откат к персонажу.Время выполнения является экспоненциальным в количестве чисел в строке.
Таким образом, мы заменим жадный квантификатор на неохотный:
".*?,.*?,.*?,.*?,.*?,13,.*?,.*?,.*?,.*?,.*?,.*?"
Это работает намного лучше для согласованной строки (коэффициент 100), но имеет почти неизменную производительность для несопоставленной строки.
Регулярное выражение-исполнитель заменяет точку классом символов "[^,]":
"[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,13,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*"
(Для этого нужно 3,7 микросекунды на строку для согласованной строки и 2,4 для несопоставленной строки на моем компьютере.)