c#regex以ical格式解析文件并用结果填充对象

我正在尝试解析具有以下格式的文件:

BEGIN:VEVENT CREATED:20120504T163940Z DTEND;TZID=America/Chicago:20120504T130000 DTSTAMP:20120504T164000Z DTSTART;TZID=America/Chicago:20120504T120000 LAST-MODIFIED:20120504T163940Z SEQUENCE:0 SUMMARY:Test 1 TRANSP:OPAQUE UID:21F61281-FB76-467F-A2CC-A666688BD9B5 X-RADICALE-NAME:21F61281-FB76-467F-A2CC-A666688BD9B5.ics END:VEVENT 

我需要在每一行上取结肠或半冒号后面的值,并将它们放入一个对象的道具中。 我正试图用Regex做这件事,但在使用它之后我基本上忘记了我所知道的关于Regex的一切(可能一年两次)。 任何帮助,将不胜感激。

通过一些示例运行此操作,看看它是否符合您的要求。 我得到了关于拆分或IndexOf的其他评论,但是如果你期望分隔符是冒号或分号,那么正则表达式可能更好。

 string line = "LAST-MODIFIED:20120504T163940Z"; var p = Regex.Match(line, "(.*)?(:|;)(.*)$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Singleline); Console.WriteLine(p.Groups[0].Value); Console.WriteLine(p.Groups[1].Value); Console.WriteLine(p.Groups[2].Value); Console.WriteLine(p.Groups[3].Value); 

编辑

这篇文章让我想到了iCal格式。

在昨天之前,我不知道iCal格式是什么。 但是,在阅读1998年的规范之后,其痛苦的显而易见的是,本页面上的答案都不足以解析内容。 并且,即使对于我的一般正则表达式,它也非常复杂。

考虑到这一点,这里有一个解析行内容的解决方案,从一般行内容解析的规范中收集。 它朝着正确的方向迈出了一步,希望有人能从中受益。 它不会继续行,也不会validation。

C#代码

 Regex iCalMainRx = new Regex( @" ^ (? [^[:cntrl:]"";:,\n]+ ) (? ; (? [^[:cntrl:]"";:,\n]+ ) = (? (?: (?:[^\S\n]|[^[:cntrl:]"";:,])* | "" (?:[^\S\n]|[^[:cntrl:]""])* "" ) (?: , (?: (?:[^\S\n]|[^[:cntrl:]"";:,])* | "" (?:[^\S\n]|[^[:cntrl:]""])* "" ) )* ) )* : (? (?:[^\S\n]|[^[:cntrl:]])* ) $ ", RegexOptions.IgnorePatternWhitespace); Regex iCalPvalRx = new Regex( @" ^ (? (?:[^\S\n]|[^[:cntrl:]"";:,])* | "" (?:[^\S\n]|[^[:cntrl:]""])* "" ) (?: ,+ (? (?:[^\S\n]|[^[:cntrl:]"";:,])* | "" (?:[^\S\n]|[^[:cntrl:]""])* "" ) )* $ ", RegexOptions.IgnorePatternWhitespace); string[] lines = { "BEGIN:VEVENT", "CREATED:20120504T163940Z", "DTEND;TZID=America/Chicago:20120504T130000", "DTSTAMP:20120504T164000Z", "DTSTART;TZID=,,,America/Chicago;Next=;last=\"this:;;;:=\";final=:20120504T120000", "LAST-MODIFIED:20120504T163940Z", "SEQUENCE:0", "SUMMARY:Test 1", "TRANSP:OPAQUE", "UID:21F61281-FB76-467F-A2CC-A666688BD9B5", "X-RADICALE-NAME:21F61281-FB76-467F-A2CC-A666688BD9B5.ics", "END:VEVENT", }; foreach (string str in lines) { Match m_content = iCalMainRx.Match( str ); if (m_content.Success) { Console.WriteLine("Key = " + m_content.Groups["name"].Value); Console.WriteLine("Value = " + m_content.Groups["value"].Value); CaptureCollection cc_pname = m_content.Groups["param_name"].Captures; CaptureCollection cc_pvalue = m_content.Groups["param_value"].Captures; if (cc_pname.Count > 0) { Console.WriteLine("Parameters: "); for (int i = 0; i < cc_pname.Count; i++) { // Console.WriteLine("\t'" + cc_pname[i].Value + "' = '" + cc_pvalue[i].Value + "'"); Console.WriteLine("\t'" + cc_pname[i].Value + "' ="); Match m_vals = iCalPvalRx.Match( cc_pvalue[i].Value ); if (m_vals.Success) { CaptureCollection cc_vals = m_vals.Groups["pvals"].Captures; for (int j = 0; j < cc_vals.Count; j++) { Console.WriteLine("\t\t'" + cc_vals[j].Value + "'"); } } } } Console.WriteLine("-------------------------"); } } 

产量

 Key = BEGIN Value = VEVENT ------------------------- Key = CREATED Value = 20120504T163940Z ------------------------- Key = DTEND Value = 20120504T130000 Parameters: 'TZID' = 'America/Chicago' ------------------------- Key = DTSTAMP Value = 20120504T164000Z ------------------------- Key = DTSTART Value = 20120504T120000 Parameters: 'TZID' = '' 'America/Chicago' 'Next' = '' 'last' = '"this:;;;:="' 'final' = '' ------------------------- Key = LAST-MODIFIED Value = 20120504T163940Z ------------------------- Key = SEQUENCE Value = 0 ------------------------- Key = SUMMARY Value = Test 1 ------------------------- Key = TRANSP Value = OPAQUE ------------------------- Key = UID Value = 21F61281-FB76-467F-A2CC-A666688BD9B5 ------------------------- Key = X-RADICALE-NAME Value = 21F61281-FB76-467F-A2CC-A666688BD9B5.ics ------------------------- Key = END Value = VEVENT ------------------------- 

吐入行并使用IndexOf(“:”)可能足以用于简单的ICAL文件而不是RegEx。

检查是否已存在ICAL解析器和相关问题ical + C# 。

尝试:

 (?[^:;]*)[:;](?[^\s]*) 

C#片段:

 Regex regex = new Regex( @"(?[^:;]*)[:;](?[^\s]*)", RegexOptions.None ); 

它需要一个字符串的任何字符,但以冒号或分号作为键,然后除了空格之外的任何其他内容作为值。

如果您想测试它或进行更改,请查看我在博客上的正则表达式检查程序: http : //blog.stevekonves.com/2012/01/an-even-better-regex-tester/ (需要silverlight)

我个人使用string.Split(’:’)为文件中的每一行。 如果您不想再次重新学习正则表达式,这样做的好处是易于阅读和理解!