【问题标题】:Match regex between curly braces匹配大括号之间的正则表达式
【发布时间】:2013-08-08 13:52:16
【问题描述】:

我需要用正则表达式匹配文本中的标记:

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

如何匹配文本中的特定标记并使用正则表达式填充值?

此外,我需要以安全的方式进行操作,并避免所有可能出现的问题,即我的标记拼写错误或有问题,如下所示:

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

附言

我试过这个:{([^}]+)}

但如果我有例如:

 {FullName}   

它有效,但如果我有它也有效

{Full{Name} ...

附: 2:

我试过这个:{=[^{^=^}]*=},但我必须使用另一个字符而不是花括号......是否可以调整它以便在没有相等字符的情况下工作?

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

所以基本上令牌在{=Token=}而不是{Token}之间

【问题讨论】:

  • 定义“避免”每一个可能的问题。你想跳过这些,还是让一些神奇的解析器决定它是好的?
  • 是正则表达式吗?使用您的“错误条件”,自定义解析器将是更好的选择。
  • 你的意思是{Full{Name}应该被正则表达式找到并正确解释?
  • 为什么不使用解析器?您已经不遗余力地实现了这个基于令牌的漂亮系统。令牌请求解析器!
  • @smerny 大括号不匹配,因为我想指出错误的情况。

标签: c# regex


【解决方案1】:

这可能会给你一个起点。随心所欲地处理异常。

该方法遍历输入字符串,在找到 OpenToken 时设置一个“打开”标志和索引。当 'open' 标志为真并且找到 CloseToken 时,它会根据索引和当前位置提取子字符串。

如果 ThrowOnError 属性设置为 true,并且在意外位置找到标记,则会引发异常。

可以轻松修改此代码以不同方式处理意外标记...例如完全跳过匹配项、按原样添加匹配项或任何您想要的。

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();
    }
}

【讨论】:

  • +1 这是解析复杂格式的唯一方法。正则表达式仅适用于模式,不适用于验证格式。出于同样的原因,正则表达式不能用于“解析 HTML”。
【解决方案2】:

你可以使用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);
        });
    }
}

以上输出:

ProductName
Street

【讨论】:

    【解决方案3】:

    我使用这个正则表达式让它工作了 90%:

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

    但是,这与{= =} 之间的我的令牌匹配,而不仅仅是{ }

    如果我有一个像{=FullName=} 这样的令牌,它将被替换为实际名称,但如果令牌是{=Full{Name=},它将不会被替换,因为它不正确并且将被忽略......这就是想法...现在,我怎样才能只使用{ }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-06
      • 1970-01-01
      • 2020-02-24
      • 2018-12-02
      • 1970-01-01
      • 2014-10-31
      • 1970-01-01
      • 2017-01-08
      相关资源
      最近更新 更多