Regex С++: извлечь подстроку
Я хотел бы извлечь подстроку между двумя другими.
ex: /home/toto/FILE_mysymbol_EVENT.DAT
или просто FILE_othersymbol_EVENT.DAT
И я хотел бы получить: mysymbol
и othersymbol
Я не хочу использовать boost или другие библиотеки. Просто стандартные материалы из С++, кроме CERN ROOT lib, с TRegexp, но я не знаю, как его использовать...
Ответы
Ответ 1
С прошлого года С++ имеет регулярное выражение, встроенное в стандарт. Эта программа покажет, как использовать их для извлечения строки, после которой:
#include <regex>
#include <iostream>
int main()
{
const std::string s = "/home/toto/FILE_mysymbol_EVENT.DAT";
std::regex rgx(".*FILE_(\\w+)_EVENT\\.DAT.*");
std::smatch match;
if (std::regex_search(s.begin(), s.end(), match, rgx))
std::cout << "match: " << match[1] << '\n';
}
Он выведет:
match: mysymbol
Следует отметить, что он не будет работать в GCC, поскольку его библиотечная поддержка регулярного выражения не очень хороша. Хорошо работает в VS2010 (и, вероятно, VS2012), и должен работать в clang.
К настоящему времени (конец 2016 года) все современные компиляторы С++ и их стандартные библиотеки полностью обновлены стандартом С++ 11, а также большинство, если не все из С++ 14. GCC 6 и предстоящий Clang 4 поддерживают большую часть следующего стандарта С++ 17.
Ответ 2
TRegexp поддерживает только очень ограниченное подмножество регулярных выражений по сравнению с другими ароматами regex. Это делает создание одного регулярного выражения, которое удовлетворяет вашим потребностям несколько неудобно.
Одно из возможных решений:
[^_]*_([^_]*)_
будет соответствовать строке до первого символа подчеркивания, а затем захватить все символы до следующего подчеркивания. Соответствующий результат матча затем найдется в группе № 1.
Но в вашем случае зачем использовать регулярное выражение? Просто найдите первое и второе вхождение разделителя _
в строке и извлеките символы между этими позициями.
Ответ 3
Если вы хотите использовать регулярные выражения, я бы рекомендовал использовать регулярные выражения С++ 11 или, если у вас есть компилятор, который еще не поддерживает их, Boost. Boost - это то, что я считаю почти частью стандартного С++.
Но для этого конкретного вопроса вам не нужны никакие формы регулярных выражений. Что-то вроде этого эскиза должно работать нормально, после того, как вы добавите все соответствующие проверки ошибок (beg != npos
, end != npos
и т.д.), Проверьте код и удалите мои опечатки:
std::string between(std::string const &in,
std::string const &before, std::string const &after) {
size_type beg = in.find(before);
beg += before.size();
size_type end = in.find(after, beg);
return in.substr(beg, end-beg);
}
Очевидно, вы можете изменить параметр std::string
на шаблон, и он должен работать нормально с помощью std::wstring
или более редко используемых экземпляров std::basic_string
.