2

I have a string

work 1 work 2 work 3 work 4 work 5

I want to obtain

work 1 work 21 work 321 work 4321 work 54321

I use this command but not work

    (?<=work\s(\d)+.)(work)(\s\d+)
    $2$3$1

The problem is that it does not record the information replaced after the first occurrence and could do to save the changes after each occurrence.

When I apply the command I get

work 1 work 21 work 32 work 43 work 54

4
  • What's your programming language? Commented Jul 2, 2016 at 17:31
  • regex c# , i use sharpdeveloper Commented Jul 2, 2016 at 17:33
  • This is not possible with one regex pass if the number of "work+digits" groups is variable. Commented Jul 2, 2016 at 17:36
  • the problem is that it does not record the information replaced after the first occurrence and could do to save the changes after each occurrence Commented Jul 2, 2016 at 17:37

2 Answers 2

1

You do not actually need an overlapping regex matching, you need to be able to match each work+space+digits and save the digits value to update at each iteration.

The regex is reduced to a mere work (?<num>\d+) (matches work, a space and captures one or more digits into the "num" group).

Use a callback method inside a Regex.Replace method:

using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Linq;
public class Test
{
    public static string num = string.Empty;
    public static void Main()
    {
        var s = "work 1 work 2 work 3 work 4 work 5";
        Console.WriteLine(Regex.Replace(s, @"work (?<num>\d+)", Repl));
    }

    public static string Repl(Match m)
    {
        num = m.Groups["num"].Value + num;
        return string.Format("work {0}", num);
    }
}

See the C# demo

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

1 Comment

Dmitry and sln suggest identical solutions using an aggregate and an anonymous method. The idea is the same: use the MatchEvaluator delegate to update the num variable.
0

You can try Regex.Replace while aggregating matches :

  String source = "work 1 work 2 work 3 work 4 work 5";
  String aggregate = "";

  // work 1 work 21 work 321 work 4321 work 54321
  String result = Regex.Replace(source, @"\d+", // or  @"(?<=work\s)\d+" pattern
    match => aggregate = match.Value + aggregate);

2 Comments

@zero625: all the answers (sln's and Wiktor Stribiżew's ones) exploit the same idea: regular expression + aggregation; the implementations, however, are slightly different (the answers uses groups, when I've performed look behind in @"(?<=work\s)\d+" pattern; I prefer lambda to delegates etc.). So the similar examples are the other answers
An unanchored lookbehind is somewhat costly in terms of regex performance, that is why I always prefer to stay away from them if I can use a capturing group. Also, the \d+ regex matching one or zero digits will match any digit sequences, not only after "work ". @zero625: BTW, if an answer proved helpful, please always consider upvoting it.

Your Answer

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