c ++ 11 (MSVS2012) регулярное выражение ищет имена файлов в несколько строк std :: string - PullRequest
0 голосов
/ 06 июня 2018

Я пытался найти четкий ответ по этому вопросу, но не смог его найти.

Итак, допустим, у меня есть строка (где \ n может быть \ r \ n - Iхочу обрабатывать оба - не уверен, если это актуально или нет)

"4345t435\ng54t a_file_123.xml rk\ngreg a_file_j34.xml fger 43t54"

Тогда я хочу получить совпадения:

  • a_file_123.xml
  • a_file_j34.xml

Вот мой тестовый код:

const str::string s = "4345t435\ng54t a_file_123.xml rk\ngreg a_file_j34.xml fger 43t54";

std::smatch matches;
if (std::regex_search(s, matches, std::regex("a_file_(.*)\\.xml")))
{
    std::cout << "total: " << matches.size() << std::endl;
    for (unsigned int i = 0; i < matches.size(); i++)
    {
        std::cout << "match: " << matches[i] << std::endl;
    }
}

Вывод:

total: 2
match: a_file_123.xml
match: 123

Я не совсем понимаю, почему матч 2 просто "123»...

1 Ответ

0 голосов
/ 06 июня 2018

У вас есть только одно совпадение, а не два, так как метод regex_search возвращает одно совпадение.Вы напечатали два значения group , Group 0 (полное совпадение, a_file_123.xml здесь) и Group 1 (здесь значение группы захвата, 123, которая является подстрокой captured с группой захвата, которую вы определили как (.*) в шаблоне).

Если вы хотите сопоставить несколько строк, вам нужно использовать итератор регулярных выражений, а не просто regex_search, который возвращает только первое совпадение.

Кроме того, .* слишком жадный ивыдаст странные результаты, если у вас более 1 совпадения на одной линии.Кажется, вы хотите сопоставить буквы или цифры, поэтому .* можно заменить на \w+.Что ж, если что-то действительно может быть, просто используйте .*?.

Используйте

const std::string s = "4345t435\ng54t a_file_123.xml rk\ngreg a_file_j34.xml fger 43t54";
const std::regex rx("a_file_\\w+\\.xml");
std::vector<std::string> results(std::sregex_token_iterator(s.begin(), s.end(), rx),
                           std::sregex_token_iterator());

std::cout << "Number of matches: " << results.size() << std::endl;
for (auto result : results)
{
    std::cout << result << std::endl;
}

См. Демонстрационную версию C ++ , получив

Number of matches: 2
a_file_123.xml
a_file_j34.xml

Примечания к регулярному выражению

  • a_file_ - буквенная подстрока
  • \\w+ - 1+ слов символов (буквы, цифры, _) (обратите внимание, что вы можете использовать [^.]*? здесь вместо \\w+, если вы хотите сопоставить любой символ, 0 или более повторений, как можно меньше, вплоть до первого .xml)
  • \\. - aточка (если вы не избежите ее, она будет соответствовать любому символу, кроме символов разрыва строки)
  • xml - буквальная подстрока.

См. демонстрационную версию regex

...