Configure text output based on pattern

Viewed 72

I'm working on a application that reads and writes to file based on config file created by user. As part of it, I want to output read text in provided by user pattern, and I can't figure out best way to do this.

Example:

Output patterns in config:

{Name} version: {1}
{Name}_{1}

while: Name - will needs to be replaced with String variable value

1,2,3... - needs to be replaced with corresponding Regex Match Group value.

Regex.Replace doesn't really work for me. It would go well with attributes like {Name}, but I cannot convert a number to regex match group.

My second idea was to match pattern against {} values and replace them using switch case, but it doesn't look like the best idea:

Regex a = new Regex("{(.*)}");

foreach (Match m in a.Matches(Pattern))
{
    switch (m.Groups[1].Value)
    {
        case "1":
            {                            
                return MatchedGroups[1].Value;
            }
        case "2":
            {                            
                return MatchedGroups[2].Value;
            }
        case "Name":
            {
                return Name;
            }
    }
}

EDIT 1:

Example to ilustrate it better, what I have and what I want to obtain:

I have:

String InputText = "12/03/2015 *** [RandomText] // 1.04.1112V";
String regex = @"([0-9/]*) \*\*\* \[([A-Za-z]*)\] \/\/ (.*)";
  // #group 1 = 12/03/2015
  // #group 2 = RandomText
  // #group 3 = 1.04.1112V
String Name = "GoogleChrome";
String OutputPattern1 = "{1} - {Name} version {3}";
String OutputPattern2 = "{Name}_{3}";

And having above variables and pattern I want to output:

#1 : 12/03/2015 - GoogleChrome version 1.04.1112V

#2 : GoogleChrome_1.04.1112V

Output Patterns will be created by user, so I cannot predict them.

1 Answers

You can use

string InputText = "12/03/2015 *** [RandomText] // 1.04.1112V";
string regex = @"([0-9/]*) \*\*\* \[([A-Za-z]*)\] \/\/ (.*)";
string Name = "GoogleChrome";
string OutputPattern1 = "{1} - {Name} version {3}";
string OutputPattern2 = "{Name}_{3}";
string rx =  @"{(?:(\d+)|Name)}";
var match  = Regex.Match(InputText, regex);
if (match.Success) {
    Console.WriteLine(
        Regex.Replace(OutputPattern1, rx, x=>
            x.Groups[1].Success? match.Groups[int.Parse(x.Groups[1].Value)].Value : Name)
    );
    Console.WriteLine(
        Regex.Replace(OutputPattern2, rx, x=>
            x.Groups[1].Success? match.Groups[int.Parse(x.Groups[1].Value)].Value : Name)
    );
}
// => 12/03/2015 - GoogleChrome version 1.04.1112V
//    GoogleChrome_1.04.1112V

See the C# demo.

The {(?:(\d+)|Name)} regex matches

  • { - a { char
  • (?:(\d+)|Name) - either one or more digits (captured into Group 1) or Name
  • } - a } char.

If the Group 1 matched, the corresponding group from the overall match is used to replace the {x} substring in the OutputPatternX, else, the Name variable text is used.

If you need to check if the Group ID exists* before replacing (say, you have {4} and your regex only has 3 groups), you will need

Regex.Replace(OutputPattern1, rx, x=>
    !x.Groups[1].Success ? Name:
        int.Parse(x.Groups[1].Value) < match.Groups.Count ? 
            match.Groups[int.Parse(x.Groups[1].Value)].Value :
            x.Value)

See this C# demo.

Related