简体   繁体   中英

Match regex between curly braces

I need to match with regular expression the tokens from text:

Hello {FullName}, I wanted to inform that your product {ProductName} is ready.
Please come to our address {Address} to get it!

How can I match the specific tokens in my text and fill the values using regex?

Also I need to do it in a safe way and avoid every possible issues where the tokens my by misspelled or have something wrong, like bellow:

**Hello {Full{Name}, I { wanted to inform that your product {{ProductName} is ready.
Please come to our } address {Addr{Street}ess} to get it!**

PS

I tried this: {([^}]+)}

But if I have for example :

 {FullName}   

it works, but it also work if I have

{Full{Name} ...

PS 2:

I tried this: {=[^{^=^}]*=} but I have to use another character instead of just curly braces ... is it possible to adjust it so that this will work without the equal character?

 {=FullName=}    - this works
 {=Full{Name=}   - this doesn't work

So basically the token is between {=Token=} instead of {Token}

This might give you a starting point. Handle the exceptions however you'd like.

The method travels through the input string, setting an 'open' flag and index when it finds the OpenToken. When the 'open' flag is true, and a CloseToken is found, it extracts a substring based on the index and current position.

If the ThrowOnError property is set to true, and a token is found in an unexpected location, it will throw an exception.

This code could easily be modified to handle the unexpected tokens differently... such as skipping that match entirely, adding the match as-is, or whatever you desire.

public class CustomTokenParser
{
    public char OpenToken { get; set; }
    public char CloseToken { get; set; }

    public bool ThrowOnError { get; set; }

    public CustomTokenParser()
    {
        OpenToken = '{';
        CloseToken = '}';
        ThrowOnError = true;
    }

    public CustomTokenParser(char openToken, char closeToken, bool throwOnError)
    {
        this.OpenToken = openToken;
        this.CloseToken = closeToken;
        this.ThrowOnError = throwOnError;
    }        

    public string[] Parse(string input)
    {
        bool open = false;
        int openIndex = -1;
        List<string> matches = new List<string>();

        for (int i = 0; i < input.Length; i++)
        {
            if (!open && input[i] == OpenToken)
            {
                open = true;
                openIndex = i;
            }
            else if (open && input[i] == CloseToken)
            {
                open = false;
                string match = input.Substring(openIndex + 1, i - openIndex - 1);
                matches.Add(match);
            }
            else if (open && input[i] == OpenToken && ThrowOnError)
                throw new Exception("Open token found while match is open");
            else if (!open && input[i] == CloseToken && ThrowOnError)
                throw new Exception("Close token found while match is not open");
        }

        return matches.ToArray();
    }
}

You may use Balancing Group Definitions :

class Program
{
    static void Main(string[] args)
    {
        string rawInput = @"**Hello {Full{Name}, I { wanted to 
            inform that your product {{ProductName} is ready.
            Please come to our } address {Addr{Street}ess} to get it!**";

        string pattern = "^[^{}]*" +
                       "(" +
                       "((?'Open'{)[^{}]*)+" +
                       "((?'Close-Open'})[^{}]*)+" +
                       ")*" +
                       "(?(Open)(?!))$";

        var tokens = Regex.Match(
            Regex.Match(rawInput, @"{[\s\S]*}").Value,
            pattern,
            RegexOptions.Multiline)
                .Groups["Close"]
                .Captures
                .Cast<Capture>()
                .Where(c =>
                    !c.Value.Contains('{') &&
                    !c.Value.Contains('}'))
                .ToList();

        tokens.ForEach(c =>
        {
            Console.WriteLine(c.Value);
        });
    }
}

The above outputs:

ProductName
Street

I kinda made it work 90% using this regex:

Regex rx = new Regex("{=[^{^=^}^<^>]*=}");

however, this matches my token between {= =} instead of just { }

If I have a token like this {=FullName=} , it will be replaces with the actual name, but if the token is {=Full{Name=} it will not be replaced because is incorrect and will be ignored ... this is the idea ... now, how can I use just { } ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM