0

I am using boost 1.67.0 regex to find matching filenames in current folder using following snippet

boost::filesystem::path p(".");
if(is_directory(p)) {

    for(auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(p), {})){
        std::stringstream ss;
        ss << entry;
        std::string filename = ss.str();
        std::cout << filename << std::endl;
        boost::regex pattern("some_\\d+_file\.txt");

        if(boost::regex_match(filename, pattern)){
            std::cout << "matched" << filename << std::endl;
        }            
    }   
}

Contents of current directory, produced by std::cout << filename << std::endl; line, are:

"./myApp.out"
"./some_0_file.txt"
"./some_1_file.txt"
"./other_file.txt"
"./some_other_file.txt"
"./some_2_file.txt"

To confirm that my matching expression is correct I consulted Perl Regular Expression Syntax. Also confirmed it using RegEx101.com, output correctly shows 3 matches as follows:

some_0_file.txt
some_1_file.txt
some_2.file.txt

Question

Is there anything wrong with my snippet or RegEx? Why boost::regex_match produce 0 match?

What have I missed?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
raidensan
  • 1,099
  • 13
  • 31

2 Answers2

2

Because regex_match considers only a FULL match. That means, you need to include ./ in your pattern. Also you escaped the last dot incorrectly. Your pattern should be:

boost::regex pattern("\\./some_\\d+_file\\.txt");

(or you can use .* as the beginning of the filepath, just not to hardcode ./)

Alternatively, you can use regex_search which returns TRUE if part of the string matches the expression.

pptaszni
  • 5,591
  • 5
  • 27
  • 43
  • Thanks for your answer. I tried both `"\\./some_\\d+_file\\.txt"` and `"\\.*some_\\d+_file\\.txt"` as my pattern. Unfortunately none of them worked. Still get 0 match. I am gonna try `regex_search`. – raidensan Sep 05 '18 at 10:20
  • 1
    Yes, as mentioned by @user338371 you also have enclosing quotes in your filenames which must be taken into consideration when looking for a full match. – pptaszni Sep 05 '18 at 11:50
2
boost::filesystem::path p(".");
if (is_directory(p)) {

    for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(p), {})) {
        std::stringstream ss;
        ss << entry.path().string(); //2
        std::string filename = ss.str();
        std::cout << filename << std::endl;
        boost::regex pattern(".*some_\\d+_file\\.txt"); //1
        if (boost::regex_match(filename, pattern)) {
            std::cout << "matched" << filename << std::endl;
        }
    }
}

1.regex_match only consider a full match

2.operator<<(std::basic_ostream<Char, Traits>& os, const path& p) will use boost::io::quoted() and add quotes to handle spaces in paths

user338371
  • 139
  • 5
  • This solved my issue, thank you. The only difference with @Ptaq66's answer is `ss << entry.path().string();` line. – raidensan Sep 05 '18 at 10:27
  • 4
    There's zero reason to bother with the stream in the first place. Also, take the regex out of the loop. Lastly, no need for the iterator range (yes, that's [surprising](https://en.cppreference.com/w/cpp/filesystem/directory_iterator/begin)) Much simplified demo: http://coliru.stacked-crooked.com/a/ca553af0515f16f3 – sehe Sep 05 '18 at 11:52