Я пишу программу, которая анализирует текст с помощью регулярного выражения. Регулярное выражение должно быть получено от пользователя. Я хочу использовать глобальный синтаксис для пользовательского ввода и внутренне преобразовать глобальную строку в регулярное выражение. Например:
"foo.? bar*"
следует преобразовать в
"^.*foo\.\w\bar\w+.*"
Каким-то образом мне нужно экранировать все значимые символы из строки, тогда мне нужно заменить glob * и? символы с подходящим синтаксисом регулярного выражения. Как это сделать наиболее удобно?





Джакарта ORO имеет реализация на Java.
Я пишу свою функцию, используя 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"
Обратите внимание, что если вы исследуете соответствующий объект, вы можете узнать больше о совпадении и использовать его для выделения или чего-то еще.
Конечно, это может быть нечто большее, но это должно быть началом.
Это верно, но вам нужно заменить замену () | \ [] и другие значимые символы в строке поиска
нет необходимости в неполных или ненадежных взломах. для этого есть функция, включенная в python
>>> import fnmatch
>>> fnmatch.translate( '*.foo' )
'.*\\.foo$'
>>> fnmatch.translate( '[a-z]*.txt' )
'[a-z].*\\.txt$'
Если вы используете python для создания регулярного выражения, вам следует использовать python для сравнения с использованием регулярного выражения, потому что sed не понимает завершающий '\\ Z (? Ms)', который фактически выводится fnmatch.translate.
Это такое прекрасное чувство, когда вам нужна функция, Google для фрагмента, и вы обнаруживаете, что эта функция находится во встроенной библиотеке. Вот почему я люблю питона.
Функция 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
Регулярное выражение выглядит немного странно. Например: «^. * Foo» можно записать как «foo». И я думаю, что глобальная звезда переводится в регулярное выражение ". *?". Куда делось место в поиске? И \ bar соответствует словам, начинающимся с "ar".