Match everything after first occurance of a number

Hey guys, I have a bunch of std::string's of versions coming from a map:

someProgram-Ver-1_11
someOtherProgram-Ver-2_13
anotherProgram-Ver-5_11

and I am trying to find a regex that will allow me to keep the tail end of those strings: 1_11, 2_13, 5_11 and save those into a new vector

can I use match for that and what would the regex be?

iterating through the strings like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
      std::map<std::string, std::string> m = versions();

    std::vector<std::string> value;

    std::string output;

    for(std::map<std::string, std::string>::iterator it = m.begin(); it != m.end(); ++it) {


      output = std::regex_replace(it->second, std::regex("^\\D*\\d+"), ""); //this is wrong its leaving off the first number


      value.push_back(output);
      std::cout << "Value: " << output << std::endl;
    }



EDIT: I see what I did wrong. The regex would be "^\\D*". That being said, how would I use match s/t I am not replacing anything but instead just keeping what I need?
Last edited on
Without using regex, then:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>
#include <map>
#include <vector>

std::string getExtension(const std::string& str, char delim = '.')
{
	const auto p {str.rfind(delim)};

	return p == std::string::npos || p == str.size() - 1 ? "" : str.substr(p + 1);
}

int main()
{
	const std::map<std::string, std::string> vers {{"a", "someProgram-Ver-1_11"}, {"b", "someOtherProgram-Ver-2_13"}, {"c", "anotherProgram-Ver-5_11"}};
	std::vector<std::string> vals;

	for (const auto& [k, v] : vers)
		vals.emplace_back(getExtension(v, '-'));

	for (const auto& v : vals)
		std::cout << v << '\n';
}



1_11
2_13
5_11

vysero wrote:
EDIT: I see what I did wrong. The regex would be "^\\D*". That being said, how would I use match s/t I am not replacing anything but instead just keeping what I need?
vysero, I think you need to use search not match...

[I'm no expert on regex so the expression may be able to be simplified]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>
#include <map>
#include <regex>

int main()
{
    const std::map<std::string, std::string> vers{ {"a", "someProgram-Ver-1_11"}, {"b", "someOtherProgram-Ver-2_13"}, {"c", "anotherProgram-Ver-5_11"} };
    std::vector<std::string> vals;
    std::smatch match;
    std::regex exp("[^\\D](.*)"); 

    for (const auto& [k, v] : vers)
    {
        std::regex_search(v, match, exp);
        if(!match.empty())
            vals.emplace_back(match.str(0));
    }

    for (const auto& v : vals)
        std::cout << v << '\n';

    return 0;
}

1_11
2_13
5_11
Last edited on
FWIW
The @GW code produces the same result with line 11
std::regex exp{"[0-9]_[0-9][0-9]"};
againtry, I was going from the subject of the thread: Match everything after first occurance of a number...but also paying attention to the comment //this is wrong its leaving off the first number and not making any assumptions about the format of all the version numbers based of a small sample. 🤷‍♂️
Is there a point being made there? c.f. Occams Razor
The point is that the expression you provided, while it will produce the same result for the given sample data might not work if say the data was someProgram-Ver-10_11...and in any case, I like to answer the question asked.
The sample doesn't have double digits. Hence Occam's Razor. I suggest you let @OP decide.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>
#include <map>
#include <regex>

int main()
{
    const std::map<std::string, std::string> vers
    {
        {"a", "someProgram-Ver-11_11"},
        {"b", "someOtherProgram-Ver-2_13"},
        {"c", "anotherProgram-Ver-5_11"},
        {"d", "anotherProgram-Ver-55_110"},
        {"e", "anotherProgram-Ver-5_11"},
        {"f", "anotherProgram-Ver-205_11"}
    };
    std::vector<std::string> vals;
    std::smatch match;

    std::regex exp{"[0-9]{1,20}_[0-9]{1,10}"};

    for (const auto& [k, v] : vers)
    {
        std::regex_search(v, match, exp);
        if(!match.empty())
            vals.emplace_back(match.str(0));
    }

    for (const auto& v : vals)
        std::cout << v << '\n';

    return 0;
}



11_11
2_13
5_11
55_110
5_11
205_11
Program ended with exit code: 0
The principle (attributed to William of Occam) that in explaining a thing no more assumptions should be made than are necessary.

Lets see now, I made no assumption about what the OP wants, they want from the first digit to the end of the string. You make the assumption that because the three samples have a particular format, them that format is the only thing required.

Anyway, you do you.
Anyway, you do you.
Pardon?
"Do you," said I, "enjoy yourself, and let this be our rendezvous. I may be absent a month or two; but do not interfere with my motions, I entreat you: leave me to peace and solitude for a short time; and when I return, I hope it will be with a lighter heart, more congenial to your own temper."--Frankenstein, 1818
@The Grey Wolf

You know, I like your regex but I am wondering. Off hand do you know how I might alter it s/t I can replace the underscore in something like 1_11 with a '.'?

Right now what I am doing is using std::replace

Last edited on
I'd probably do something like...(if I thought regex was the way to go)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <string>
#include <map>
#include <regex>

int main()
{
    std::map<std::string, std::string> vers
    {
        {"a", "someProgram-Ver-11_11"},
        {"b", "someOtherProgram-Ver-2_13"},
        {"c", "anotherProgram-Ver-5_11"},
        {"d", "anotherProgram-Ver-55_110"},
        {"e", "anotherProgram-Ver-5_11"},
        {"f", "anotherProgram-Ver-205_11"}
    };
    std::vector<std::string> vals;
    std::smatch match;  
    std::regex exp("(-\\d+)_(\\d+)");    

    for (auto& [k, v] : vers)
    {
        v = std::regex_replace(v, exp, "$1.$2");
        std::cout << v << '\n';
    }
    return 0;
}

someProgram-Ver-11.11
someOtherProgram-Ver-2.13
anotherProgram-Ver-5.11
anotherProgram-Ver-55.110
anotherProgram-Ver-5.11
anotherProgram-Ver-205.11
...unless you are talking about pulling the numbers out and changing the _ in one op...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>
#include <map>
#include <regex>

int main()
{
    std::map<std::string, std::string> vers
    {
        {"a", "someProgram-Ver-11_11"},
        {"b", "someOtherProgram-Ver-2_13"},
        {"c", "anotherProgram-Ver-5_11"},
        {"d", "anotherProgram-Ver-55_110"},
        {"e", "anotherProgram-Ver-5_11"},
        {"f", "anotherProgram-Ver-205_11"}
    };
    std::vector<std::string> vals;
    std::smatch match;  
    std::regex exp("(\\d+)_(\\d+)");    

    for (auto& [k, v] : vers)
    {
        std::regex_search(v, match, exp);
        vals.emplace_back(match.str(1) + "." + match.str(2));
    }

    for (const auto& v : vals)
        std::cout << v << '\n';

    return 0;
}


11.11
2.13
5.11
55.110
5.11
205.11
@The Grey Wolf

Yeah actually, that's perfect thanks!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <string>
#include <map>
#include <regex>

int main()
{
    std::map<std::string, std::string> vers
    {
        {"a", "someProgram-Ver-11_11"},
        {"b", "someOtherProgram-Ver-2_13"},
        {"c", "anotherProgram-Ver-5.11"},
        {"d", "anotherProgram-Ver-55_110"},
        {"e", "anotherProgram-Ver-5555_11"},
        {"f", "anotherProgram-Ver-205_11"}
    };
    
    std::smatch m;
    std::regex reg_1{"[0-9]{1,20}_[0-9]{1,10}"};
    std::regex reg_2{"_"};
    std::string output;
    std::vector<std::string> vals;
    
    for (auto& [k, v] : vers)
    {
        if(regex_search(v, m, reg_1) )
        {
            regex_replace
            (std::back_inserter(output), v.begin(), v.end(), reg_2,  ".");
            
            vals.push_back(output);
            output.clear();
        }
    }
    
    for(auto i:vals)
    {
        std::cout << i << '\n';
    }
    return 0;
}



someProgram-Ver-11.11
someOtherProgram-Ver-2.13
anotherProgram-Ver-55.110
anotherProgram-Ver-5555.11
anotherProgram-Ver-205.11
Program ended with exit code: 0
Topic archived. No new replies allowed.