0

I've found this topic which only explains how to replace the first regex match. What about some n'th match?

Say I have a string and a regex like these:

std::string str  = "fast cast dust crust must last rust";
std::regex  expr = " .(a|u)st";

How can I replace, say, the third match with some other sequence? std::regex_replace allows to replace either all matches or the first one. I'm also thinking about std::regex_iterator, but still can't figure out how to apply it in this task. What are the most convenient ways to solve the problem?

Kaiyakha
  • 1,463
  • 1
  • 6
  • 19
  • Make a regex that first matches the first n-1 occurences followed by one extra occurence – Pepijn Kramer Jun 23 '23 at 12:35
  • It should be mentioned that there are a lot of solutions here on SO with regexps that are designed to specifically replace an Nth match. Like `^((?:.*?pattern){n-1}.*?)pattern` and replace with `$1` (backreference to Group 1). Does it sound sufficient for you? See [the regex demo](https://regex101.com/r/55j6tD/1). – Wiktor Stribiżew Jun 23 '23 at 13:30
  • @WiktorStribiżew it still requires messing around with the expression itself, which is what I'd like to avoid – Kaiyakha Jun 23 '23 at 14:02

1 Answers1

1

I've managed to come up with my own solution. I use std::string::replace taking a pair of iterators in the first std::sub_match from the advanced std::sregex_iterator:

std::string str = "fast cast dust crust must last rust";
std::regex expr{" .(a|u)st"};
std::sregex_iterator regex_it{str.cbegin(), str.cend(), expr};

std::advance(regex_it, 2);
str.replace(regex_it->cbegin()->first, regex_it->cbegin()->second, " lol");
std::cout << str << std::endl;

One could add some extra iterator validations if they wish. I'll keep it brief.

The output is:

fast cast dust crust lol last rust

It's worth mentioning, however, that std::regex_replace returns a modified copy whereas the solution above changes the string in place. Also, one should be careful as the iterators in the sub_matches may become invalidated once the replacement has been completed.

Kaiyakha
  • 1,463
  • 1
  • 6
  • 19