【问题标题】:C# Parsing Keyword lines for outputC# 解析输出的关键字行
【发布时间】:2014-12-25 14:21:20
【问题描述】:

我们正在尝试制作我们在正常维护周期期间应用的 Microsoft KBase 更新的更改日志。 我们要解析以下特定行的信息。示例如下:

Operation           : 1
ResultCode          : 2
HResult             : 0
Date                : 10/7/2014 10:27:50 AM
UpdateIdentity      : System.__ComObject
Title               : Update for Microsoft Silverlight (KB2977218)
Description         : This update to Silverlight improves security, reliability, accessibility support, startup performance, enhances line-of-business support and includes several fixes to better support rich internet applications. This update is backward compatible with web applications built using previous versions of Silverlight.
UnmappedResultCode  : 0
ClientApplicationID : AutomaticUpdates
ServerSelection     : 1
ServiceID           : 
UninstallationSteps : System.__ComObject
UninstallationNotes : 
SupportUrl          : http://go.microsoft.com/fwlink/?LinkID=105787
Categories          : System.__ComObject

我们想要的输出是:

Title               : Update for Microsoft Silverlight (KB2977218)
Date                : 10/7/2014 10:27:50 AM
Description         : This update to Silverlight improves security, reliability, accessibility support, startup performance, enhances line-of-business support and includes several fixes to better support rich internet applications. This update is backward compatible with web applications built using previous versions of Silverlight.

我正在尝试编写一个简单的 C# 应用程序,我们会将原始数据粘贴到富文本框中,单击一个按钮并在另一个富文本框中获得所需的输出。有一种可能有用的“关键字:数据”模式。

我创建了表单和表单上的元素。我试图找到一种方法来搜索关键字,但这不会产生我们寻求的结果。我们希望关键字或行可以这么说,如您所见,描述可能是多行。

我目前没有任何示例代码可发布,因为我不知道从哪里开始执行此任务。任何示例代码都将有助于完成此任务。

【问题讨论】:

  • 它真的是多行还是你只是猜测,因为你的文本是这样被包装的? Description : 后面的字符串中实际上是否有 \n 字符?请注意最新的编辑如何表明Description 只是一个很长的行。
  • 许多简单的方法可以做到这一点。您可以编写一个匹配 [anything]:[anything] 的正则表达式,然后读取您的匹配项,并且只获取匹配“title”或“date”或“description”的第一个元素的匹配项,或者使用 split() 对其进行标记行尾 (\r\n) 和冒号 (:)。
  • 看起来你可以让 PowerShell 为你解决这个问题。如果它的事件日志详细信息,您真的要提取记录,将其复制到文本框然后拆分吗?听起来像很多手工工作要做..
  • @dbc 和 Dominic Zukiewicz - 我只需要一个文本解析器来完成我试图为另一个同行解决的任务。不过谢谢你的建议。

标签: c# parsing richtextbox


【解决方案1】:

您可以尝试以下Regex 模式:

(?<=\b[KEYWORD]\b\s*:\s*).*

只需将[KEYWORD] 替换为您要查找的实际关键字即可。例如(?&lt;=\bTitle\b\s*:\s*).* 将返回Update for Microsoft Silverlight (KB2977218)。以下是您在代码中的使用方式:

private string GetDataFromKeyword(string source, string keyword)
{
    return Regex.Match(source, string.Format(@"(?<=\b{0}\b\s*:\s*).*", keyword)).Value.Trim();
}

然后这样称呼它:

string data = GetDataFromKeyword(textbox.Text, "Title");

模式说明:

(?&lt;=):是positive look-behind的表示法。

\b[KEYWORD]\b\s*:\s*:匹配整个单词[KEYWORD],后跟任意数量的空格,后跟:,后跟任意数量的空格。

.*:匹配后面的任何内容,本质上是Keyword: Data 对中的Data

编辑

如果给定关键字有多个实例,则可以使用Matches() 方法代替Match()

private IEnumerable<string> GetDataFromKeyword(string source, string keyword)
{
    return Regex.Matches(source, string.Format(@"(?<=\b{0}\b\s*:\s*).*", keyword))
            .Cast<Match>().Select(match => match.Value.Trim());
}

现在var data = GetDataFromKeyword(textbox.Text, "Title"); 返回一个匹配列表,您可以通过它枚举:

var titles = GetDataFromKeyword(textbox.Text, "Title").ToArray();
var dates = GetDataFromKeyword(textbox.Text, "Date").ToArray();
var descriptions = GetDataFromKeyword(textbox.Text, "Description").ToArray();

for (int i = 0; i < titles.Count(); i++)
{
    string block = string.Format("Title: {0}, Date: {1}, Description: {2}", titles[i], dates[i], descriptions[i]);
    MessageBox.Show(string.Format("Block {0}: {1}", i+1, block));
}

请注意,这将假定您拥有相同数量的 titledatedescription 条目。我不确定您的要求是什么,但这只是迭代列表的一个示例。根据您的需要进行更改。

【讨论】:

  • 第一个文本框中粘贴多个条目的情况如何?这只会解决 1 个实例。所以看来我需要一种计算不同“块”数据的方法,然后用循环解析每个数据块?
  • @Deadphoenix 如果多个条目是指关键字的多个实例,那么您仍然可以使用正则表达式。请参阅我编辑的答案。
  • 很抱歉,我仍在学习 C#,我将如何枚举列表。我的尝试没有成功。另外,我想在输出时在块中返回标题、日期和描述。
  • 只需使用forforeach 循环。 GetDataFromKeyword() 的结果只是一个字符串列表(匹配项)。
  • @Deadphoenix 查看答案。
【解决方案2】:

我通常不喜欢基于正则表达式的解决方案——几乎总是有一种更可读的方式来实现你的目标。

这样的事情应该可以帮助您入门。也有很多重构的机会:

var keywords = new List<string>() { "Keyword1", "Keyword2", "Keyword3" };

var lines = File.ReadLines(@"c:\path\to\file.txt");

foreach (var line in lines)
{
    foreach (var keyword in keywords)
    {
        if (line.StartsWith(keyword))
        {
            // found a match, do something.
            // Split on ":"? etc.
        }
    }
}

正如我所说,非常快速和肮脏,但是 1) 它可以工作 2) 它是可读的并且 3) 你可以做很多简单的重构。

【讨论】:

  • 如果你对它有深入的了解,一切都是可读的:)
猜你喜欢
  • 2016-10-28
  • 2013-07-14
  • 1970-01-01
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多