0

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.

0

1 Answer 1

1

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

  • A numbered capture group is specified whenever you wrap an expression in (regex)
  • To keep your expression orderly, you can specify non-capturing groups like this (?:regex)
  • For easier backreferencing, create a named capture group like this: (?<name>regex)
  • To refer to a named capture group in a replacement string, use ${name}, instead of using $1

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

Sign up to request clarification or add additional context in comments.

4 Comments

I changed variables toBeReplaced = "(\d{2})-(\d{2})-(\d{4})" and replacedWith = "$1/$2/$3" but no luck.
You might have to escape the backslashes (\\d{2})-(\\d{2})-(\\d{4})
Is it matching it at all? For example if you just replace with "test" does it output it correctly? If so, maybe the capture groups need to be backreferenced with \1 instead of $1
IIRC, ECMA script's RegExp, which is used in C++ <regex> (with POSIX character class extension) doesn't have named capturing group.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.