Match everything after first occurance of a number

Oct 14, 2021 at 9:52pm
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 Oct 14, 2021 at 10:34pm
Oct 15, 2021 at 9:47am
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

Oct 15, 2021 at 11:15am
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 Oct 15, 2021 at 11:19am
Oct 15, 2021 at 11:44am
FWIW
The @GW code produces the same result with line 11
std::regex exp{"[0-9]_[0-9][0-9]"};
Oct 15, 2021 at 12:20pm
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. 🤷‍♂️
Oct 15, 2021 at 12:32pm
Is there a point being made there? c.f. Occams Razor
Oct 15, 2021 at 12:48pm
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.
Oct 15, 2021 at 1:19pm
The sample doesn't have double digits. Hence Occam's Razor. I suggest you let @OP decide.
Oct 15, 2021 at 1:30pm
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
Oct 15, 2021 at 1:37pm
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.
Oct 15, 2021 at 1:39pm
Anyway, you do you.
Pardon?
Oct 15, 2021 at 3:04pm
"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
Oct 15, 2021 at 4:28pm
@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 Oct 15, 2021 at 4:46pm
Oct 15, 2021 at 5:37pm
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
Oct 15, 2021 at 6:05pm
...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
Oct 15, 2021 at 9:45pm
@The Grey Wolf

Yeah actually, that's perfect thanks!
Oct 16, 2021 at 2:11am
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.