[英]How do I match everything except two characters?
我需要匹配双花括号之间的所有字符,但是我需要能够在一个大字符串中找到多个匹配项。
我一直在使用RegEx测试器,因为我正在C#中执行此操作: http : //derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx单行”已选中,因为我想要。 匹配\\ 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场比赛,这是从我尝试使用否定的前瞻(?!\\}\\})
的第一个{{
到最后一个}}
所有内容,但这似乎对我不起作用。 不幸的是, [^\\}\\}]
不匹配两个花括号,只匹配一个。
我不是一个带正则表达式的菜鸟,但是这个确实让我着迷。 我到处都在寻找答案,所以现在我希望有人可以帮助我。
我非常感谢专家的任何帮助。
一些东西:
您正在使用?
在包含*
捕获组中。 *
表示“ 0次或多次”,因此基本上内容已经是可选的。 使用?
什么也没做
\\{\\{(?<field>[^>]*)[ > ]?(?<looptemplate>[^\\}\\}].*)\\}\\}
[ > ]
匹配1个字符。 空格或>
。 您可能是说(?: > )
(匹配" > "
(忽略引号,否则SO不会渲染空格)并将其组合在一起。
\\{\\{(?<field>[^>]*)(?: > )?(?<looptemplate>[^\\}\\}].*)\\}\\}
[^\\}\\}]
与[^\\}]
。 否定的字符类不适用于字符串,它们仅适用于内部的每个字符,因此多次写入不会改变任何内容。 我想这就是您尝试否定前瞻的原因。 是的,但是您需要检查重复的每个字符的条件。 否则,您只需要检查一次,就可以looptemplate
不是以\\}\\}
开头,而是以.*
触发。 所以组.
和前瞻:
\\{\\{(?<field>[^>]*)(?: > )?(?<looptemplate>(?:(?!\\}\\}).)*)\\}\\}
您的(?: > )
是可选的,因此如果您有一些{{...}}
不包含它(只有field
部分,您将遇到与以前相同的问题,只是这次使用[^>]
。在此也包括前瞻:
\\{\\{(?<field>(?:(?!\\}})[^>])*)(?: > )?(?<looptemplate>(?:(?!\\}\\}).)*)\\}\\}
顺便说一句,使用否定字符类或超前字符的替代方法是使用不贪心的重复。 如果可以使用否定字符类,则通常更可取,因为它具有同等可读性,但通常比ungreedy修饰符更有效,因为它不需要回溯。 在您的情况下,您必须使用超前(因为您不想跳过两个连续字符的模式,而不仅仅是一个字符)。 在这种情况下,前瞻可能会避免回溯,从而抵消性能提升,而且前瞻通常不太容易理解。 因此,您可能只想在这里进行不愉快的重复(在重复量后面加上?
):
\{\{(?<field>(?:(?!\}})[^>])*)(?: > )?(?<looptemplate>.*?)\}\}
请注意,您不能对field
使用不满意的重复,因为(?: > )
是可选的。 这将导致field
为空,其他所有内容(包括可能由looptemplate
匹配的" > "
, 除非将>
与looptemplate
一起包含在可选组中:
\{\{(?<field>[^>]*?)(?: > (?<looptemplate>.*?))?\}\}
最后一点。 这只是一个品味问题,但让我向您介绍另一种逃避形式。 在字符类中时,许多元字符不是元字符(仍然只有]
, -
, ^
和\\
)。 因此,您可以将元字符包装在字符类中以对其进行转义:
[{][{](?<field>[^>]*?)(?: > (?<looptemplate>.*?))?[}][}]
正如我所说,这只是一个建议,但对于大多数字符,我发现它比使用反斜杠更具可读性。
另外,我也想检查“ SingleLine”。 匹配\\ n
如果取消选中“单行”,它将起作用。 所以很明显你.
是问题。 一个简单的解决方案是使用.*?
而不是.*
因为它会非贪婪地选择所需的内容(而不是贪婪地选择尽可能多的内容)。 另一个解决方案是替换.
通过更具体的内容,例如否定的前瞻,因为您可能不想匹配另一个{{
甚至}}
内部的{{
但是在这种情况下,非贪婪的解决方案要容易得多。
您可能还应该更改字段字符类的乘法器,以使其与循环模板中已经存在的内容不匹配。
另请注意, [ > ]
是字符类,将选择空格或>
。 因此它不会选择" > "
。 如果需要的话,请不要放在括号内:
\{\{(?<field>[^>]*?)? > (?<looptemplate>[^}].*?)?\}\}
在您的情况下,由于您可能希望将looptemplate设置为可选,因此您可能想像这样使用非捕获组来做到这一点:
\{\{(?<field>[^>]*?)?(?: > (?<looptemplate>[^}].*?))?\}\}
还有最后的一点; 如果你想.
为了匹配换行符,最好在需要的地方提供示例。
(好的,另外请注意,正如m.buettner在他的答案中正确提到的那样,字符类仅需提及每个字符一次;此外,您无需在字符类中转义花括号,因此将其简化为[^}]
)
那这个呢:
\{\{.*?\}\}
.*?
与.*
相似,但采用延迟匹配,而不是贪婪。 这意味着它会停止匹配,并尝试尽快继续匹配正则表达式的其余部分,而不是贪婪的匹配,后者会在继续进行正则表达式的其余部分之前尝试消耗尽可能多的内容。
因此,适用于:“ {{this}}和that}}
\\{\\{.*?\\}\\}
匹配“ {{this}}”
和
\\{\\{.*\\}\\}
匹配“ {{this}}和that}}”
编辑开始:
好的,所以我更改了文本文件。
<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>
然后我在Regex新构造函数中添加了一个参数...具有讽刺意味的是,该选项是“ SingleLine”
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("}}", ""));
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.