当前位置: 首页 > 编程语言 > C#

String.Format类实用程序的正则表达式分享

时间:2023-04-11 00:50:43 C#

String.Format类实用程序的正则表达式占位符。这是一个例子:strings=StringTemplate.Format("Hello{Name}。今天是{Date:D},现在是{Date:T}。",new{Name="World",Date=DateTime.Now});为实现此结果,我查找占位符并将其替换为索引。然后我将生成的格式字符串传递给String.Format。这工作正常,除非有双括号,这是一个转义序列。此处描述了所需的行为(与String.Format相同):等等...但是我当前的正则表达式不检测转义序列,并且始终将括在括号中的子字符串视为占位符,因此我得到类似“Hello{0}”的内容。这是我当前的正则表达式:privatestaticRegex_regex=newRegex(@"{(?w+)(?:[^}]+)?}",RegexOptions.Compiled);如何修改此正则表达式以忽略转义花括号?看起来真的很难的是我应该根据括号的数量是奇数还是偶数来检测占位符......我想不出用正则表达式来做的简单方法,它甚至可能吗?为了完整起见,这里是StringTemplate类的完整代码:publicclassStringTemplate{privatestring_template;privatestaticRegex_regex=newRegex(@"{(?w+)(?:[^}]+)?}",RegexOptions.Compiled);publicStringTemplate(stringtemplate){if(template==null)thrownewArgumentNullException("template");this._template=模板;}publicstaticimplicitoperatorStringTemplate(strings){returnnewStringTemplate(s);}publicoverridestringToString(){return_template;}publicstringFormat(IDictionaryvalues){if(values==null){thrownewArgumentNullException("values");}字典索引=newDictionary();object[]array=newobject[values.Count];诠释我=0;foreach(values.Keys中的字符串键){array[i]=values[key];indexes.Add(key,i++);}匹配评估器evaluator=(m)=>{if(m.Success){stringkey=m.Groups["key"].Value;stringformat=m.Groups["format"].Value;整数指数=-1;如果(indexes.TryGetValue(key,outindex)){returnstring.Format("{{{0}{1}}}",index,format);}}returnstring.Format("{{{0}}}",m.Value);};stringtemplateWithIndexes=_regex.Replace(_template,evaluator);返回string.Format(templateWithIndexes,array);}privatestaticIDictionaryMakeDictionary(objectobj){Dictionarydict=newDictionary();foreach(varpropinobj.GetType().GetProperties()){dict.Add(prop.Name,prop.GetValue(obj,null));}返回字典;}publicstringFormat(objectvalues){returnFormat(MakeDictionary(values));}publicstaticstringFormat(stringtemplate,IDictionaryvalues){returnnewStringTemplate(template).Format(values);}publicstaticstringFormat(stringtemplate,objectvalues){returnnewStringTemplate(template).Format(values);}}您可以使用正则表达式配衡对,然后找出如何处理大抽号请记住,.NET正则表达式不是“正则”。类程序{staticvoidMain(string[]args){vard=newDictionary{{"Name","World"}};vart=new测试();Console.WriteLine(t.Replace("你好{Name}",d));Console.WriteLine(t.Replace("你好{{Name}}",d));Console.WriteLine(t.Replace("你好{{{Name}}}",d));Console.WriteLine(t.Replace("你好{{{{Name}}}}",d));控制台.ReadKey();}}classTest{privateRegexMatchNested=newRegex(@"{(?>([^{}]+)|{(?)|}(?))*(?(D)(?!))}",RegexOptions.IgnorePatternWhitespace|RegexOptions.Compiled|RegexOptions.Singleline);publicstringReplace(stringinput,Dictionaryvars){Matchermatcher=newMatcher(vars);返回MatchNested.Replace(input,matcher.Replace);}privateclassMatcher{privateDictionaryVars;publicMatcher(Dictionaryvars){Vars=vars;}publicstringReplace(Matchm){stringname=m.Groups[1].Value;intlength=(m.Groups[0].Length-name.Length)/2;字符串内部=(长度%2)==0?名称:变量[名称];返回MakeString(内部,长度/2);}privatestringMakeString(stringinner,intbraceCount){StringBuildersb=newStringBuilder(inner.Length+(braceCount*2));sb.Append('{',braceCount);某人追加(内部);sb.Append('}',braceCount);返回sb.ToString();}}}使用regex是很有可能的——但我完全不相信它是最可维护的解决方案,因为你真的只对这里的花括号和冒号感兴趣(我认为),我个人会避免使用正则表达式。我将构建一个标记序列,每个标记都是文字或格式字符串。通过沿着绳子走来构造它,注意左括号和右括号。然后评估序列只是连接标记的问题,并根据需要格式化每个标记。话又说回来,我真的不喜欢正则表达式-只是偶尔它们很棒,但很多时候它们感觉有点矫枉过正。在这种情况下,也许有一些聪明的方法可以让他们做你想做的事......顺便说一句,你需要定义在大括号不匹配的情况下你想要发生什么,例如{{Name}foo使用正则表达式通常很容易确定奇偶校验。例如,这里有一个表达式匹配任何带有偶数A的字符串,但不匹配奇数A:(AA)*所以您需要做的就是找到只匹配奇数{s和}s的表达式。{({{)*}(}})*(尽管转义了字符)。因此,将这个想法添加到您当前的表达式中会产生类似{({{)*(?w+)(?:[^}]+)?}(}})*的结果,但是,这与Cardinality所做的双花括号不同不匹配。换句话说,{{{将匹配},因为它们都很奇怪。正则表达式无法评估东西,因此您无法找到与您想要的基础相匹配的表达式。实际上,您应该做的是使用自定义解析器解析字符串,该解析器读取字符串并计算{butnotinstances{{以便将它们与}instancesbutnot}}实例匹配。我想您会发现这就是.NET中的字符串格式化程序无论如何在幕后所做的事情,因为正则表达式不太适合解析任何类型的嵌套结构。或者您可以同时使用这两种想法:将底层标记与正则表达式进行匹配,然后使用快速检查结果匹配来验证大括号的平衡。但这可能最终会变得混乱和间接。对于这种情况,您通常最好编写自己的解析器。我最终使用了一种类似于加文建议的技术。我更改了正则表达式,使其匹配占位符周围的所有大括号:privatestaticRegex_regex=newRegex(@"(?{+)(?w+)(?:[^}]+)?(?}+)",RegexOptions.Compiled);我更改了MatchEvaluator的逻辑,以便正确处理转义的大括号:MatchEvaluatorevaluator=(m)=>{if(m.Success){stringopen=m.Groups["open"].Value;stringclose=m.Groups["close"].Value;stringkey=m.Groups["key"].Value;stringformat=m.Groups["format"].Value;if(open.Length%2==0)returnm.Value;打开=RemoveLastChar(打开);关闭=RemoveLastChar(关闭);整数指数=-1;if(indexes.TryGetValue(key,outindex)){returnstring.Format("{0}{{{1}{2}}}{3}",open,index,format,close);}else{returnstring.Format("{0}{{{{{{1}}}{2}}}{3}",open,key,format,close);}}返回m.Value;};如果需要,我依靠String.Format抛出FormatException。我做了一些单元测试,到目前为止似乎工作正常......谢谢大家的帮助!以上就是C#学习教程分享的全部内容:String.Format类实用程序的正则表达式。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: