2

I am trying to match all files that have the extension .nef - The match must be case insensitive.

regex e("(.*)(\\.NEF)",ECMAScript|icase);
...
if (regex_match ( fn1, e )){
    //Do Something
}

here fn1 is a string with a file name.

However, this "does something" only with files with .NEF (upper case) extensions. .nef extensions are ignored.

I also tried -

regex e("(.*)(\\.[Nn][Ee][Ff])");

and

regex e("(.*)(\\.[N|n][E|e][F|f])");

both of which resulted in a runtime error.

terminate called after throwing an instance of 'std::regex_error'
  what():  regex_error
Aborted (core dumped)

My code is compiled using -

g++ nefread.cpp -o nefread -lraw_r -lpthread -pthread -std=c++11 -O3

What am I doing wrong? This is my basic code. I want to extend it to match more file extensions .nef, .raw, .cr2 etc.

Lord Loh.
  • 2,437
  • 7
  • 39
  • 64
  • 2
    That exception probably doesn't have anything do with your regex string, but it's because you're using gcc's regex implementation, which is broken. gcc will ship with a working `` in version 4.9 – Praetorian Jan 28 '14 at 04:11
  • Why do you try to match "." with "\\."? Shouldn't it be "\."? – Maria Ines Parnisari Jan 28 '14 at 04:12
  • @Praetorian - Oh! So some of these http://cpprocks.com/wp-content/uploads/c++11-regex-cheatsheet.pdf will not work?? – Lord Loh. Jan 28 '14 at 04:13
  • @l19 - The first ` \ ` (c++) is to escape the second ` \ ` (regex) which is to escape the ` . `. – Lord Loh. Jan 28 '14 at 04:14
  • [`^(.*)(\.)([Nn][Ee][Ff])$`](http://rubular.com/r/XxHenYdwwS) seems to work correctly. though you should escape the `'\'` as you already know, and includes the extension as a separate capture group (which can be convenient). If this doesn't work on your end you're regex has issues. What regex are you using anyway? – WhozCraig Jan 28 '14 at 04:18
  • @WhozCraig - I am using the standard regex (http://www.cplusplus.com/reference/regex/) and that expression did not match any file :-( – Lord Loh. Jan 28 '14 at 04:42

1 Answers1

5

Your original expression is correct, and should produce the desired result. The problem is with the gcc implementation of <regex>, which is broken. This answer explains the historical reasons why it so, and also says that gcc4.9 will ship with a working <regex> implementation.

Your code works using Boost.Regex

#include <iostream>
#include <string>
#include <boost/regex.hpp>

int main()
{
    // Simple regular expression matching
    boost::regex expr(R"((.*)\.(nef))", boost::regex_constants::ECMAScript |
                                        boost::regex_constants::icase);
    //                ^^^           ^^
    // no need escape the '\' if you use raw string literals
    boost::cmatch m;

    for (auto const& fname : {"foo.nef", "bar.NeF", "baz.NEF"}) {
        if(boost::regex_match(fname, m, expr)) {
            std::cout << "matched: " << m[0] << '\n';
            std::cout << "         " << m[1] << '\n';
            std::cout << "         " << m[2] << '\n';
        }
    }
}

Live demo

Community
  • 1
  • 1
Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • Thank you. I think I shall use the boost implementation the next time I code. For now, I have used `regex e("(.*)(\\.)(((N|n)(E|e)(F|f))|((C|c)(R|r)2))",ECMAScript|icase);` - the `icase` is useless. to match `.nef` and `.cr2` the way I want it. – Lord Loh. Jan 28 '14 at 04:42
  • 1
    That should work, but you really don't need that horrendous looking expression if you use the `icase` flag. `regex expr(R"dlm((.*)\.(nef|cr2))dlm", ECMAScript|icase);` will get you the same result. – Praetorian Jan 28 '14 at 04:45