c++regexlinuxg++g++-4.7

Regular Expression replacing pattern with pattern


I am new to regular expressions. I was googling and found some solutions and then I come up with my own solution as following

#include <string.h>
#include <regex.h>
#include <iostream>

int rreplace (char *buf, int size, regex_t *re, char *rp){
    char *pos;
    int sub, so, n;
    regmatch_t pmatch [10];
    if (regexec (re, buf, 10, pmatch, 0))
        return 0;
    for (pos = rp; *pos; pos++)
        if (*pos == '\\' && *(pos + 1) > '0' && *(pos + 1) <= '9'){
            so = pmatch [*(pos + 1) - 48].rm_so;
            n = pmatch [*(pos + 1) - 48].rm_eo - so;
            if (so < 0 || strlen (rp) + n - 1 > size)
                return 1;
            memmove (pos + n, pos + 2, strlen (pos) - 1);
            memmove (pos, buf + so, n);
            pos = pos + n - 2;
        }

    sub = pmatch [1].rm_so; /* no repeated replace when sub >= 0 */
    for (pos = buf; !regexec (re, pos, 1, pmatch, 0); ){
        n = pmatch [0].rm_eo - pmatch [0].rm_so;
        pos += pmatch [0].rm_so;
        if (strlen (buf) - n + strlen (rp) + 1 > size)
            return 1;
        memmove (pos + strlen (rp), pos + n, strlen (pos) - n + 1);
        memmove (pos, rp, strlen (rp));
        pos += strlen (rp);
        if (sub >= 0)
            break;
    }
    return 0;
}

int main (int argc, char **argv){
    //buf [FILENAME_MAX],
    char rp [FILENAME_MAX];
    regex_t re;
    string toBeReplaced = "-";
     string replacedWith = "/";
    regcomp (&re, toBeReplaced.c_str(), REG_ICASE);

    string buf;
    cout << "Enter date separated with dash" << endl;
    cin >> buf;

    char * replacedWith_ = new char[replacedWith.size() + 1];
    std::copy(replacedWith.begin(), replacedWith.end(), replacedWith_);
    replacedWith_[replacedWith.size()] = '\0'; // don't forget the terminating 0


    char * buf_ = new char[buf.size() + 1];
    std::copy(buf.begin(), buf.end(), buf_);
    buf_[buf.size()] = '\0'; // don't forget the terminating 0


    rreplace (buf_, FILENAME_MAX, &re, strcpy (rp, replacedWith_));

    cout<<  buf_ << endl;
    regfree (&re);
    delete[] replacedWith_;
    return 0;
}

Well this code works fine if my string contains something like

22-04-2013

and it will change it to

22/04/2013. but I want it to be generic something like

\d\d-\d\d-\d\d\d\d

to be replaced with

\d\d/\d\d/\d\d\d\d

as I want it to be generic. Also I am working in linux g++. Most of the on-line solutions available are on different platforms. I also tried the following

string toBeReplaced = "\d[-]\d";
&
string replacedWith = "\d/\d";

but no luck. and I get \d/\d when I enter 3-4. I dont know why. Forgive me if I asked something stupid.

EDIT

My problem is match a pattern and replace it with a pattern. like digit followed by a hyphen should be replaced with digit followed by a slash.


Solution

  • Problem

    You cannot replace a match with more regex, you will get the literal text \d/\d instead.


    Solution

    To accomplish your goal, you need replace using a backreferenced capture group() like so:

    (\d{2})-(\d{2})-(\d{4})

    Your replacement string would be as follows:

    $1/$2/$3

    As you can tell, each capture group is numbered. There are three capture groups in the above regex.


    Further notes on Capture Groups

    Please note in the above examples, regex should be replaced by your desired Regular Expression.

    Some syntax for backrefencing may vary with different Regex Implementations, for example: \1 instead of $1


    Demonstration

    Here's a demo for a visual representation of what I'm talking about:

    Regex101 Example, Capture Groups on a Datetime String