Создать регулярное выражение из выражения glob

Я пишу программу, которая анализирует текст с помощью регулярного выражения. Регулярное выражение должно быть получено от пользователя. Я хочу использовать глобальный синтаксис для пользовательского ввода и внутренне преобразовать глобальную строку в регулярное выражение. Например:

"foo.? bar*" 

следует преобразовать в

"^.*foo\.\w\bar\w+.*"

Каким-то образом мне нужно экранировать все значимые символы из строки, тогда мне нужно заменить glob * и? символы с подходящим синтаксисом регулярного выражения. Как это сделать наиболее удобно?

Регулярное выражение выглядит немного странно. Например: «^. * Foo» можно записать как «foo». И я думаю, что глобальная звезда переводится в регулярное выражение ". *?". Куда делось место в поиске? И \ bar соответствует словам, начинающимся с "ar".

PEZ 15.01.2009 12:17
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
22
1
18 577
6

Ответы 6

Я пишу свою функцию, используя C++ и boost :: regex

std::string glob_to_regex(std::string val)
{
    boost::trim(val);
    const char* expression = "(\\*)|(\\?)|([[:blank:]])|(\\.|\\+|\\^|\\$|\\[|\\]|\\(|\\)|\\{|\\}|\\\\)";
    const char* format = "(?1\\\\w+)(?2\\.)(?3\\\\s*)(?4\\\\$&)";
    std::stringstream final;
    final << "^.*";
    std::ostream_iterator<char, char> oi(final);
    boost::regex re;
    re.assign(expression);
    boost::regex_replace(oi, val.begin(), val.end(), re, format, boost::match_default | boost::format_all);
    final << ".*" << std::ends;
    return final.str();
}

похоже, все работает нормально

Я не уверен, что полностью понимаю требования. Если я предполагаю, что пользователи хотят найти текстовые «записи», соответствующие их поисковым запросам, я думаю, что этот грубый способ сработает в качестве начала.

Сначала избегайте всего, что имеет значение для регулярных выражений. Затем используйте замены без регулярных выражений для замены (теперь экранированных) глобальных символов и создайте регулярное выражение. Как в Python:

regexp = re.escape(search_string).replace(r'\?', '.').replace(r'\*', '.*?')

Для строки поиска в вопросе создается регулярное выражение, которое выглядит так (необработанное):

foo\..\ bar.*?

Используется во фрагменте кода Python:

search = "foo.? bar*"
text1 = 'foo bar'
text2 = 'gazonk foo.c bar.m m.bar'

searcher = re.compile(re.escape(s).replace(r'\?', '.').replace(r'\*', '.*?'))

for text in (text1, text2):
  if searcher.search(text):
    print 'Match: "%s"' % text

Производит:

Match: "gazonk foo.c bar.m m.bar"

Обратите внимание, что если вы исследуете соответствующий объект, вы можете узнать больше о совпадении и использовать его для выделения или чего-то еще.

Конечно, это может быть нечто большее, но это должно быть началом.

Это верно, но вам нужно заменить замену () | \ [] и другие значимые символы в строке поиска

Evgeny Lazin 15.01.2009 13:59

нет необходимости в неполных или ненадежных взломах. для этого есть функция, включенная в python

>>> import fnmatch
>>> fnmatch.translate( '*.foo' )
'.*\\.foo$'
>>> fnmatch.translate( '[a-z]*.txt' )
'[a-z].*\\.txt$'

Если вы используете python для создания регулярного выражения, вам следует использовать python для сравнения с использованием регулярного выражения, потому что sed не понимает завершающий '\\ Z (? Ms)', который фактически выводится fnmatch.translate.

Paul 10.12.2020 07:24

Это такое прекрасное чувство, когда вам нужна функция, Google для фрагмента, и вы обнаруживаете, что эта функция находится во встроенной библиотеке. Вот почему я люблю питона.

Matthew Leingang 01.04.2021 22:27

Функция jPaq RegExp.fromWildExp делает нечто подобное. Следующее взято из примера, который находится на главной странице сайта:

// Find a first substring that starts with a capital "C" and ends with a
// lower case "n".
alert("Where in the world is Carmen Sandiego?".findPattern("C*n"));

// Finds two words (first name and last name), flips their order, and places
// a comma between them.
alert("Christopher West".replacePattern("(<*>) (<*>)", "p", "$2, $1"));

// Finds the first number that is at least three numbers long.
alert("2 to the 64th is 18446744073709551616.".findPattern("#{3,}", "ol"));

В R есть функция glob2rx, включенная в базовый дистрибутив:

http://stat.ethz.ch/R-manual/R-devel/library/utils/html/glob2rx.html

Другие вопросы по теме