Изменить 2: Для практической демонстрации того, почему это остается важным, смотрите не далее, чем stackoverflow, вызванное регулярным выражением (2016-07-20)!
Изменить: Этот вопрос значительно изменился с тех пор, как я впервые спросил его. См. Ниже для двух быстрых + совместимых, но не полностью полнофункциональных реализаций. Если вы знаете больше или лучше реализаций, пожалуйста, укажите их, но пока еще не идеальная реализация!
Где можно найти надежную реализацию Regex?
Знает ли кто-нибудь о нормальной линейной реализации регулярного выражения без обратного отслеживания (System.Text.RegularExpressions
) для .NET или родной и разумно используемой из .NET? Чтобы быть полезным, ему нужно было бы:
- имеет временную сложность наихудшего вычисления регулярных выражений O (m * n), где m - длина регулярного выражения, а n - длина ввода.
- имеют нормальную временную сложность O (n), так как почти никакие регулярные выражения фактически не вызывают экспоненциальное состояние-пространство, или, если они могут, делают это только на минутном подмножестве вход.
- имеют разумную скорость построения (т.е. потенциально экспоненциальные DFA)
- предназначено для использования людьми, а не математиками - например, Я не хочу переопределять классы символов юникода: Символьные классы стиля .NET или PCRE являются плюсом.
Бонусные баллы:
- бонусные баллы для практичности, если он реализует функции на основе стека, которые позволяют обрабатывать вложенность за счет потребления памяти O (n + m), а не O (m).
- бонусные баллы для или для захвата подвыражений или (если есть экспоненциальное число возможных совпадений подвыражения, то перечисление всех из них по своей сути экспоненциально - но перечисление первого малое не должно быть и аналогично для замены). Вы можете обходиться без какой-либо функции, используя другую, поэтому достаточно одного из них.
- лот-бонусные баллы для обработки регулярных выражений как значений первого класса (так что вы можете принять объединение, пересечение, конкатенацию, отрицание - в частности, отрицание и пересечение, так как очень сложно выполнять строковые манипуляции определение регулярного выражения)
- ленивое соответствие, т.е. совпадение в неограниченных потоках без помещения всего в память - плюс. Если потоки не поддерживают поиск, захват подвыражений и/или замены не могут (в общем) возможны за один проход.
- Backreferences вне, они фундаментально ненадежны; то есть всегда могут экспоненциально воздействовать на случаи патологического ввода.
Такие алгоритмы существуют (это основная теория автоматов...) - но существуют ли практически доступные реализации, доступные из .NET?
Фон: (вы можете пропустить это)
Мне нравится использовать Regex для быстрого и грязного очищения текста, но я неоднократно сталкивался с проблемами, когда общее использование NFA, используемое perl/java/python/.NET, демонстрирует экспоненциальное поведение. К сожалению, эти случаи довольно легко вызвать, как только вы начнете автоматически генерировать регулярные выражения. Даже неэкспоненциальная производительность может стать чрезвычайно низкой при чередовании регулярных выражений, которые соответствуют одному и тому же префиксу - например, в действительно базовом примере, если вы возьмете словарь и превратите его в регулярное выражение, ожидайте ужасную производительность.
Для краткого обзора того, почему существуют лучшие реализации и существуют с 60-х годов, см. Регуляция регулярных выражений может быть простой и быстрой.
Не совсем практичные варианты:
- Почти идеальный: Инструментарий FSA. Может компилировать регулярные выражения для быстрых реализаций C в DFA + NFA, также позволяет датчикам (!), Иметь регулярные выражения первого класса (инкапсуляция yay!), Включая синтаксис для пересечения и параметризации. Но это в прологе... (почему что-то с такими практическими функциями недоступно на основном языке?)
- Быстрый, но непрактичный: полный парсер, например отличный ANTLRобычно поддерживает надежные быстрые регулярные выражения. Однако синтаксис antlr гораздо более подробен и, конечно же, позволяет создавать конструкции, которые не могут генерировать действительные парсеры, поэтому вам нужно найти некоторое безопасное подмножество.
Хорошие реализации:
- RE2 - библиотека с открытым исходным кодом google, нацеленная на разумную совместимость с PCRE минус обратные ссылки. Я думаю, что это преемник unix-порта plan9 regex lib, данный автору.
- TRE - также в основном совместим с PCRE и даже делает обратные ссылки, хотя с помощью тех, которые вы теряете гарантии скорости. И он имеет мега-отличный примерный режим соответствия!
К сожалению, обе реализации - это С++, и для взаимодействия с .NET требуется взаимодействие.