【问题标题】:How to extract specific data with headers included如何提取包含标题的特定数据
【发布时间】:2015-08-17 18:03:57
【问题描述】:

我有以下形式的数据,我想从中提取特定信息:

    f
    hj
13:45
    A
    Cd
    F
    RT
14:10
    df
    gj
    G
.. goes on

假设,我想要 Fgj.. 之间的所有内容,包括时间戳,我将如何去做。我知道如何获取从 F 到 gj 的行,但我也不知道如何包含时间戳,我对 c# 很陌生。任何帮助将不胜感激。

输出应该类似于

13:45
    F
    RT
14:10
    df
    gj

编辑 :::

public static void search_HstrLog()
        {
            int counter = 0;

            string[] hist_Logs = Directory.GetFiles(@"c:\logs");

            string line;

            for (int i = 0; i < hist_Logs.Count(); i++)
            {
                StreamReader reader = new StreamReader(hist_Logs[i]);

                bool betweenStartAndEnd = false;
                while ((line = reader.ReadLine()) != null)
                {
                    {
                        {

                        string start = "RUN";
                        string end = "STOP";


                            if(line.Contains(start))
                                betweenStartAndEnd = true;

                            if (betweenStartAndEnd || isTimeStamp(line))
                                Console.WriteLine(line);

                            if(line.Contains(end))
                                betweenStartAndEnd = false;
                        }
                    }
                }

                reader.Close();
            }
        }

    public static bool isTimeStamp(string line)
    {
        return Regex.IsMatch(line, @"^\d{2}:\d{2} ?[a-z]*$");
    }

这就是我现在所拥有的,正则表达式已被轻微更新,因为时间戳行还可以包含文本,包括开始和结束术语,例如14:22 RUN

此外,这是数据看起来更具体的准确版本

14:22 RUN
     - abc
     - bfg
         dmf
            -rkc
15:33 
     dbv
        -fjh
        -fjs

所以在上面的例子中,如果 start 是 RUN 而 end 是 fjh,那么结果将是......

 14:22 RUN
         - abc
         - bfg
             dmf
                -rkc
 15:33 
      dbv
         -fjh

如果 start 是 bfg 而 end 是 dbv,则输出将是 -

14:22 
    - bfg
         dmf
            -rkc
15:33 
     dbv

【问题讨论】:

  • 这个不清楚。如果您知道获取线路很热门,那么为什么不包括时间戳?您是在问如何将值解析为DateTime?您能否展示您迄今为止所做的任何尝试,并具体告诉我们为什么它不起作用?
  • 我实际上搜索了 F,一旦找到,就写下每一行,直到找到 gj,但是我不知道如何获得我错过的第一个时间戳。我如何返回并检索它?
  • 解析文本(文件)总是有点乏味,正如人们所希望的那样。通常它需要或多或少的原始解析器实现。
  • 您可能需要的语法可能如下所示:DataBlock ::= &lt;Time&gt; | &lt;Time&gt;&lt;TextBlock&gt;. TextBlock ::= &lt;Text&gt; | &lt;Text&gt;&lt;TextBlock&gt;. 如果您以这种方式解析,您总是有时间作为 DataBlock 的一部分,并且在完全解析 DataBlock 之后,您会查找您的 Text" F",然后更改状态并继续解析,直到找到一个带有 Text "gj" 的 DataBlock。

标签: c# timestamp


【解决方案1】:

基本上,如果您在开始值和结束值之间,您想要跟踪,然后您需要一种方法来识别时间戳。这里我使用正则表达式,但您可以将其更改为其他任何内容,包括使用DateTime.ParseExact。如果您需要在比较之前删除前导空格和尾随空格,您可能还需要使用string.Trim

string start = "F";
string end = "gj";
bool betweenStartAndEnd = false;
foreach(var line in lines)
{
    if(line == start)
        betweenStartAndEnd = true;

    if(betweenStartAndEnd || isTimeStamp(line))
        Console.WriteLine(line);

    if(line == end)
        betweenStartAndEnd = false;
}

public static bool isTimeStamp(string line)
{
    return Regex.IsMatch(line, @"^\d{2}:\d{2}$");
}

【讨论】:

  • 这正在产生输出,但我没有看到 F 之前的第一个时间戳。那个时间戳仍然丢失
  • @sparta93 尝试isTimeStamp(line.Trim()) 以确保删除所有前导和尾随空格。
  • 这适用于像var lines = new List&lt;string&gt; { "f", "hj", "13:45", "A", "Cd", "F", "RT", "14:10", "df", "gj", "G" }; 这样的输入。尝试调试以查看第一个时间戳的“行”值究竟是什么。
  • 嘿,请检查我的编辑。我已经尝试了很多东西,但我仍然没有得到第一个时间戳。谢谢。
  • 您是否尝试过^\d{2}:\d{2} 的正则表达式。基本上只需检查该行是否以时间戳开头。
【解决方案2】:

使用如下代码所示的状态机

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        enum State
        {
            FIND_START,
            COLLECT_DATA,
            STOP_COLLECTING
        }
        static void Main(string[] args)
        {
            string input =
                    "14:22 RUN\n" +
                         "- abc\n" +
                         "- bfg\n" +
                             "dmf\n" +
                                "-rkc\n" +
                    "15:33\n" +
                         "dbv\n" +
                            "-fjh\n" +
                            "-fjs\n";

            StringReader reader = new StringReader(input);

            string inputLine = "";
            string output = "";
            State state = State.FIND_START;
            while ((inputLine = reader.ReadLine()) != null)
            {
                switch (state)
                {
                    case State.FIND_START:
                        if (inputLine.Contains("RUN"))
                        {
                            output += inputLine + "\n";
                            state = State.COLLECT_DATA;
                        }
                        break;
                    case State.COLLECT_DATA:
                        output += inputLine + "\n";
                        if (inputLine == "dbv") state = State.STOP_COLLECTING;
                        break;
                    case State.STOP_COLLECTING:
                        break;

                }
            }

        }
    }
}

【讨论】:

  • 这只是将开头从“F”更改为“hj”。如果您将开始更改为“F”,它仍然不会包含第一个时间戳。
  • 第一个时间戳是 13:45 将被包括在内。该代码是如何收集部分文本字符串的示例,可以根据需要进行修改。
  • 问题是如何包含所有时间戳,而不管开始和结束。您的代码不这样做。你所做的只是改变开始,使它在第一个时间戳之前。
  • 在解析文本时,不能只查找特定数据而不知道数据之前的精确数据顺序。如果不将其与其他标题相关联,时间将毫无意义。文本解析并不简单。我已经这样做了 40 年,并且了解如何正确正确关联数据。
  • @jdweng 嘿,我尝试了您的解决方案,但没有成功,请查看我上面的编辑以获取更具体的描述。抱歉,如果问题含糊不清。谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-04-03
  • 2021-12-26
  • 2013-01-19
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多