C#Regex,有没有更有效的方法来解析由符号括起的字符串?
我不确定是否可以问。。。但事情是这样的 我实现了一个使用regex解析字符串的方法,每个匹配都通过委托解析,并带有一个顺序(实际上,顺序并不重要——我想,等等,是吗?…但我是这样写的,它没有经过完全测试):C#Regex,有没有更有效的方法来解析由符号括起的字符串?,c#,regex,string,C#,Regex,String,我不确定是否可以问。。。但事情是这样的 我实现了一个使用regex解析字符串的方法,每个匹配都通过委托解析,并带有一个顺序(实际上,顺序并不重要——我想,等等,是吗?…但我是这样写的,它没有经过完全测试): Pattern Regex.Replace:@”(?我认为这是对这个问题的独特理解。您可以构建一个类,该类将用于逐块构造整个模式。该类将负责生成MatchEvaluator委托,该委托也将传递给Replace class RegexReplacer { public string
- Pattern Regex.Replace:
@”(?我认为这是对这个问题的独特理解。您可以构建一个类,该类将用于逐块构造整个模式。该类将负责生成
委托,该委托也将传递给MatchEvaluator
Replace
因为您希望每个替换程序都知道它是否成功,并且因为我们正在通过使用组名对此进行攻击,所以您希望确保每个组名都是不同的。确保这一点的简单方法是使用与变量名相同的名称,因为在同一范围内不能有两个同名的变量 您可以在上面看到,我正在分别构建模式的每个部分,但在构建过程中,我将前一个替换项作为第四个参数传递给当前替换项。这将构建替换项链。构建完成后,我将使用最后一个构建的替换项来生成整个模式和求值器。如果您使用除以外的任何项,那么您只会最后,只需将生成的模式和求值器传递给class RegexReplacer { public string Pattern { get; private set; } public string Replacement { get; private set; } public string GroupName { get; private set; } public RegexReplacer NextReplacer { get; private set; } public RegexReplacer(string pattern, string replacement, string groupName, RegexReplacer nextReplacer = null) { this.Pattern = pattern; this.Replacement = replacement; this.GroupName = groupName; this.NextReplacer = nextReplacer; } public string GetAggregatedPattern() { string constructedPattern = this.Pattern; string alternation = (this.NextReplacer == null ? string.Empty : "|" + this.NextReplacer.GetAggregatedPattern()); // If there isn't another replacer, then we won't have an alternation; otherwise, we build an alternation between this pattern and the next replacer's "full" pattern constructedPattern = string.Format("(?<{0}>{1}){2}", this.GroupName, this.Pattern, alternation); // The (?<XXX>) syntax builds a named capture group. This is used by our GetReplacementDelegate metho. return constructedPattern; } public MatchEvaluator GetReplaceDelegate() { return (match) => { if (match.Groups[this.GroupName] != null && match.Groups[this.GroupName].Length > 0) // Did we get a hit on the group name? { return this.Replacement; } else if (this.NextReplacer != null) // No? Then is there another replacer to inspect? { MatchEvaluator next = this.NextReplacer.GetReplaceDelegate(); return next(match); } else { return match.Value; // No? Then simply return the value } }; } }
方法 请记住,这种方法更多地针对所描述的问题。它可能适用于更一般的场景,但我只使用了您介绍的内容。此外,由于这更像是一个解析问题,解析器可能是正确的选择——尽管学习曲线会更高Replace
还请记住,我没有分析过这段代码。它当然不会在目标字符串上循环多次,但在替换过程中确实涉及到额外的方法调用。您肯定希望在您的环境中对其进行测试。我认为这是一个独特的问题。您可以构建一个类,用于构造e一块一块的整体模式。此类将负责生成
委托,该委托也将传递给MatchEvaluator
Replace
因为您希望每个替换程序都知道它是否成功,并且因为我们正在通过使用组名对此进行攻击,所以您希望确保每个组名都是不同的。确保这一点的简单方法是使用与变量名相同的名称,因为在同一范围内不能有两个同名的变量 您可以在上面看到,我正在分别构建模式的每个部分,但在构建过程中,我将前一个替换项作为第四个参数传递给当前替换项。这将构建替换项链。构建完成后,我将使用最后一个构建的替换项来生成整个模式和求值器。如果您使用除以外的任何项,那么您只会最后,只需将生成的模式和求值器传递给class RegexReplacer { public string Pattern { get; private set; } public string Replacement { get; private set; } public string GroupName { get; private set; } public RegexReplacer NextReplacer { get; private set; } public RegexReplacer(string pattern, string replacement, string groupName, RegexReplacer nextReplacer = null) { this.Pattern = pattern; this.Replacement = replacement; this.GroupName = groupName; this.NextReplacer = nextReplacer; } public string GetAggregatedPattern() { string constructedPattern = this.Pattern; string alternation = (this.NextReplacer == null ? string.Empty : "|" + this.NextReplacer.GetAggregatedPattern()); // If there isn't another replacer, then we won't have an alternation; otherwise, we build an alternation between this pattern and the next replacer's "full" pattern constructedPattern = string.Format("(?<{0}>{1}){2}", this.GroupName, this.Pattern, alternation); // The (?<XXX>) syntax builds a named capture group. This is used by our GetReplacementDelegate metho. return constructedPattern; } public MatchEvaluator GetReplaceDelegate() { return (match) => { if (match.Groups[this.GroupName] != null && match.Groups[this.GroupName].Length > 0) // Did we get a hit on the group name? { return this.Replacement; } else if (this.NextReplacer != null) // No? Then is there another replacer to inspect? { MatchEvaluator next = this.NextReplacer.GetReplaceDelegate(); return next(match); } else { return match.Value; // No? Then simply return the value } }; } }
方法 请记住,这种方法更多地针对所描述的问题。它可能适用于更一般的场景,但我只使用了您介绍的内容。此外,由于这更像是一个解析问题,解析器可能是正确的选择——尽管学习曲线会更高Replace
还请记住,我没有分析过这段代码。它当然不会在目标字符串上循环多次,但在替换过程中会涉及额外的方法调用。您肯定希望在您的环境中测试它。this
将.Replace(@“\%”,@“%”)
替换为%
,为了将%
替换为\%
,您的模式必须是%
。如果您不知道,这是一个以@开头的逐字字符串,它被读取为文字字符,转义序列不被解析,例如:“\\”不被解析为“\,并保留为“\\”。您的示例显示结果为“\\%”->“\%”,而不是“%”。我觉得奇怪,你刚才只指出了这一部分,因为还有更多。你考虑过使用像ANTLR这样的完整解析器吗?嗯,我尝试过寻找解析文本命令的最佳方式。但不幸的是,我不知道这些解析器是否能像我这样做:“[TextBox,[Options]”。这些[Options]有很多参数(大约30+或更多),它们可以作为默认值和自由排列保留。例如:“TextBox,Name=Qufad,Clear,ShowName,Draw,Draw,Draw,Draw,Draw,Draw,Show”。示例2:“TextBox,BorderLeft=两次,BorderRight=两次,BorderTop=一半,BorderBottom=自动”。虽然我必须实现一个大的switch case语句来正确解析所有内容。所有这些命令都调用method或modify字段。此
.Replace(@“\%”,@“%”)将
替换为%
,为了将%
替换为\%
,您的模式必须是%
如果您不知道,这是一个以@开头的逐字字符串,它被读取为文字字符,转义序列没有被解析,例如:“\\”没有被解析为“\”,它仍然是“\\”。您的示例显示结果是“\\\%”->“\%”,而不是“%”。我觉得奇怪,你刚才只指出了这一部分,因为还有更多。你考虑过使用像ANTLR这样的完整解析器吗?嗯,我尝试过寻找解析文本命令的最佳方式。但不幸的是,我不知道这些解析器是否能像我这样做:“[TextBox,[Options]”。这些[Options]有很多参数(大约30+或更多),它们可以作为默认值和自由排列被忽略。例如:“TextBox,Name=Qufad,Clear,ShowName,Draw,Draw,Druck,Show”。示例2:“TextBox,BorderLeft=Twic。Replace(@“\%”,@“\%”)
string target = @"$global name$ Money \$9000 %local var% It's over 9000\% I@hit@the@ground@too@hard qw\@op"; RegexReplacer dollarWrapped = new RegexReplacer(@"(?<!\\)\$[^$]+\$", "motherofglobalvar", "dollarWrapped"); RegexReplacer slashDollar = new RegexReplacer(@"\\\$", string.Empty, "slashDollar", dollarWrapped); RegexReplacer percentWrapped = new RegexReplacer(@"(?<!\\)%[^%]+%", "lordoflocalvar", "percentWrapped", slashDollar); RegexReplacer slashPercent = new RegexReplacer(@"\\%", string.Empty, "slashPercent", percentWrapped); RegexReplacer singleAt = new RegexReplacer(@"(?<!\\)@", " ", "singleAt", slashPercent); RegexReplacer slashAt = new RegexReplacer(@"\\@", "@", "slashAt", singleAt); RegexReplacer replacer = slashAt; string pattern = replacer.GetAggregatedPattern(); MatchEvaluator evaluator = replacer.GetReplaceDelegate(); string result = Regex.Replace(target, pattern, evaluator);