Создать регулярное выражение из выражения - PullRequest
20 голосов
/ 15 января 2009

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

"foo.? bar*" 

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

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

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

Ответы [ 6 ]

49 голосов
/ 12 октября 2009

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

>>> import fnmatch
>>> fnmatch.translate( '*.foo' )
'.*\\.foo$'
>>> fnmatch.translate( '[a-z]*.txt' )
'[a-z].*\\.txt$'
2 голосов
/ 15 января 2009

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

Сначала избегайте всего, что имеет значение для регулярных выражений. Затем используйте замены без регулярных выражений для замены (теперь экранированных) глобальных символов и построения регулярного выражения. Как и в 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"

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

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

1 голос
/ 14 марта 2011

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

// 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"));
1 голос
/ 15 января 2009

Я пишу свою собственную функцию, используя 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();
}

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

1 голос
/ 15 января 2009

Jakarta ORO имеет реализацию в Java .

0 голосов
/ 10 июня 2015

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...