C# 如何匹配除两个字符以外的所有字符?

C# 如何匹配除两个字符以外的所有字符?,c#,regex,C#,Regex,我需要匹配双大括号之间的所有字符,但我需要能够在一个大字符串中找到多个匹配项 我一直在使用这个正则表达式测试器,因为我在C#中这样做: 另外,我检查了“单线”,因为我想要。匹配\n 下面是我正在匹配的字符串的示例: <div class="nest-1-2"> <dl> <dt>Type:</dt> <dd>{{(Entity)Field Name.separator(, ) > [:Name:]}}<

我需要匹配双大括号之间的所有字符,但我需要能够在一个大字符串中找到多个匹配项

我一直在使用这个正则表达式测试器,因为我在C#中这样做: 另外,我检查了“单线”,因为我想要。匹配\n

下面是我正在匹配的字符串的示例:

<div class="nest-1-2">
    <dl>
    <dt>Type:</dt>
    <dd>{{(Entity)Field Name.separator(, ) > [:Name:]}}</dd>
    <dt>At:</dt>
    <dd>{{(Entity)Field Name > [:Name:]}}</dd>
    <dt>Team:</dt>
    <dd>{{(Entity)Field Name.separator(, ) > [:First Name:] [:Last Name:]}}</dd>
    </dl>
</div>

类型:
{{(实体)字段名.分隔符(,)>[:名称:}
地址:
{{(实体)字段名>[:名称:}}
小组:
{{(实体)字段名.分隔符(,)>[:名字:][:姓氏:}
下面是我正在使用的正则表达式:

\{\{(?<field>[^>]*)?[ > ]?(?<looptemplate>[^\}\}].*)?\}\}
\{(?[^>]*)?[>](?[^\}].*)?[>}
我遇到的问题是,我希望中的所有内容都匹配下一个}之前的所有文本,而这是匹配上一个而不是下一个。所以我得到了1个匹配项,从第一个
{{
到最后一个
}
我试着使用否定的前瞻
(?!\}})
,但这似乎对我不起作用。不幸的是,
[^\}]
不匹配两个大括号,它只匹配一个大括号

我并不是一个完全不懂正则表达式的人,但这一个真的让我着迷了。我到处寻找答案,所以现在我希望有人能帮助我

我非常感谢专家们的帮助。

这个怎么样:

\{\{.*?\}\}
*?
*
类似,但使用惰性匹配,而不是贪婪匹配。这意味着它会停止匹配,并尝试尽快继续匹配regex的其余部分,而不是贪婪匹配,贪婪匹配会尝试在进入regex的其余部分之前消耗尽可能多的资源

所以,适用于:“{{this}}和that}”

\{.*.\}
匹配“{{this}”

\{.\}
匹配“{this}}和that}}”

这个呢:

\{\{.*?\}\}
*?
*
类似,但使用惰性匹配,而不是贪婪匹配。这意味着它会停止匹配,并尝试尽快继续匹配regex的其余部分,而不是贪婪匹配,贪婪匹配会尝试在进入regex的其余部分之前消耗尽可能多的资源

所以,适用于:“{{this}}和that}”

\{.*.\}
匹配“{{this}”

\{.*\}
匹配“{this}}和that}}”

一些事情:

  • 您在包含
    *
    的捕获组上使用了
    *
    表示“0次或更多次”,因此基本上内容已经是可选的。使用
    没有任何作用

    \{\{(?<field>[^>]*)[ > ]?(?<looptemplate>[^\}\}].*)\}\}
    
  • [^\}]
    [^\}]
    相同。否定字符类不处理字符串,它们只处理其中的每个字符,所以多次写入一个字符不会改变任何东西。我想这就是你为什么尝试消极前瞻的原因。这是正确的,但您需要检查每个重复字符的条件。否则,您只需检查一次,
    循环模板
    不是以
    \}
    开头,而是以
    *
    开始。因此,将
    和“前瞻”分组:

    \{\{(?<field>[^>]*)(?: > )?(?<looptemplate>(?:(?!\}\}).)*)\}\}
    
  • 顺便说一下,使用否定字符类或lookaheads的另一种方法是使用ungreedy重复。如果您可以使用否定字符类,这通常是更好的,因为它的可读性相同,但通常比ungreedy修饰符更有效,因为它不需要回溯。在您的情况下,您必须使用前向(因为有一种模式是两个连续字符,而不是一个字符,您不想经过)。在这种情况下,前瞻可能会抵消避免回溯带来的性能增益,而且前瞻通常可读性稍差。因此,您可能只想在这里使用一个不发音的重复(在重复量词后面加上
    ):

    最后一个音符。这只是品味的问题,但让我向你介绍另一种逃跑方式。在字符类中,许多元字符都不是元字符(只有
    ]
    -
    ^
    \
    仍然是元字符)。因此,您可以将元字符包装在字符类中以转义:

    [{][{](?<field>[^>]*?)(?: > (?<looptemplate>.*?))?[}][}]
    
    [{][{](?[^>]*?)(?:>(?*?)?[}][}]
    
    正如我所说,这只是一个建议,但对于大多数字符,我发现这比使用反斜杠更具可读性。

    有几点:

  • 您在包含
    *
    的捕获组上使用了
    *
    表示“0次或更多次”,因此基本上内容已经是可选的。使用
    没有任何作用

    \{\{(?<field>[^>]*)[ > ]?(?<looptemplate>[^\}\}].*)\}\}
    
  • [^\}]
    [^\}]
    相同。否定字符类不处理字符串,它们只处理其中的每个字符,所以多次写入一个字符不会改变任何东西。我想这就是你为什么尝试消极前瞻的原因。这是正确的,但您需要检查每个重复字符的条件。否则,您只需检查一次,
    循环模板
    不是以
    \}
    开头,而是以
    *
    开始。因此,将
    和“前瞻”分组:

    \{\{(?<field>[^>]*)(?: > )?(?<looptemplate>(?:(?!\}\}).)*)\}\}
    
  • 顺便说一下,使用否定字符类或lookaheads的另一种方法是使用ungreedy重复。如果您可以使用否定字符类,这通常是更好的,因为它的可读性相同,但通常比ungreedy修饰符更有效,因为它不需要回溯。在您的情况下,您必须使用前向(因为有一种模式是两个连续字符,而不是一个字符,您不想经过)。在这种情况下,前瞻可能会抵消避免回溯带来的性能增益,而且前瞻通常可读性稍差。所以你可能只想和一只无舌的白鼬一起去
    [{][{](?<field>[^>]*?)(?: > (?<looptemplate>.*?))?[}][}]
    
    <div class="nest-1-2">
        <dl>
        <dt>Type:</dt>
        <dd>{{(Entity)Field Name.separator(, ) > [:Name:]
        foo came up
        boo is here too}}</dd>
        <dt>At:</dt>
        <dd>{{(Entity)Field Name > [:Name:]}}</dd>
        <dt>Team:</dt>
        <dd>{{(Entity)Field Name.separator(, ) > [:First Name:] [:Last Name:]}}</dd>
        </dl>
    </div>
    
    System.Text.RegularExpressions.Regex Y = new System.Text.RegularExpressions.Regex("{{(.*?)\\}}", System.Text.RegularExpressions.RegexOptions.Singleline);
    
    namespace a
    {
        class Program
        {
            static void Main(string[] args)
            {
                string X = System.IO.File.ReadAllText("C:\\Users\\rnirnberger\\Documents\\a.txt");
                System.Text.RegularExpressions.Regex Y = new System.Text.RegularExpressions.Regex("{{(.*?)\\}}");
                System.Text.RegularExpressions.MatchCollection Z = Y.Matches(X);
                foreach (System.Text.RegularExpressions.Match match in Z)
                {
                    Console.WriteLine(match.Value);
    
                    //If you want to strip out the double-braces
                    //↓↓↓↓
    
                    //Console.WriteLine(match.Value.Replace("{{", "").Replace("}}", ""));
                }
            }
        }
    
    \{\{(?<field>[^>]*?)? > (?<looptemplate>[^}].*?)?\}\}
    
    \{\{(?<field>[^>]*?)?(?: > (?<looptemplate>[^}].*?))?\}\}