简体   繁体   English

在文本文件(C#)中匹配的单词后打印该行

[英]Print the line after a matching word from a text file (C#)

I am reading from a text file which basically looks like: 我正在阅读一个基本上看起来像的文本文件:

>Name
>12345

>Name2
>32458

>Name3
>82745

and so on. 等等。 I want it so once the program detects Name it prints both Name and the line after it: 12345 to the console. 我想要它,所以一旦程序检测到Name它会打印Name和它后面的行: 12345到控制台。

Here is my code so far: 到目前为止,这是我的代码:

if (args[0] == "prog1")
{
    List<string> lines = File.ReadAllLines(filename).ToList();

        foreach (var line in lines)
        {
            if (line.Contains("Name"))
            {
                Console.WriteLine(line);
            }
        }
}

So far this only prints "Name" to the console and I am unsure of how to get it to print the line after it as well. 到目前为止,这只会向控制台打印"Name" ,我不确定如何在它之后打印

You can't access the next line if you're using a foreach loop (behind the scenes a foreach loop sets up an enumerator but you can't access it see the third solution for a way to make your own enumerator that you can control directly), but you can either: 如果您正在使用foreach循环,则无法访问下一行(在幕后,foreach循环设置枚举器,但您无法访问它,请参阅第三种解决方案,以便制作您可以控制的自己的枚举器直接),但你可以:

  • Switch to using a for loop, and print the n+1 line 切换到使用for循环,并打印n + 1行
         if (args[0] == "prog1")
         {
            string[] lines = File.ReadAllLines(filename);

            for(int i = 0; i< lines.Length; i++)
            {
                var line = lines[i];
                if (line.Contains("Name"))
                {
                    Console.WriteLine(line);
                    Console.WriteLine(lines[++i]); // ++i means "increment i, then use it" so it is incremented first then used to access the line
                }
            }
        }
  • Keep using the foreach and toggle a boolean to true, that will cause the next line to print even though it doesn't contain "Name", then toggle it off when you do the print 继续使用foreach并将布尔值切换为true,这将导致下一行打印,即使它不包含“Name”,然后在执行打印时将其关闭

        if (args[0] == "prog1")
        {
            List<string> lines = File.ReadAllLines(filename).ToList();

            bool printLine = false;
            foreach (var line in lines)
            {
                if (line.Contains("Name"))
                {
                    printLine = true;
                    Console.WriteLine(line);
                }
                else if(printLine){
                    Console.WriteLine(line);
                    printLine = false;
                }
            }
        }
  • Set up your own enumerator so you can move it onto the next thing yourself 设置你自己的枚举器,这样你就可以自己将它移到下一件事上
      string[] lines = File.ReadAllLines(filename);

      var enumerator = lines.GetEnumerator(); //the enumerator starts "before" the first line of the file

      while (enumerator.MoveNext()){ //moveNext returns true until the enumerator reaches the end
        if(enumerator.Current.Contains("Name")){
          Console.WriteLine(enumerator.Current);   //print current line
          if(enumerator.MoveNext())                //did we move to next line?
            Console.WriteLine(enumerator.Current); //print next line
        }
      }

For what it's worth, I'f use the classic for loop as i find it easiest to read, understand, maintain.. 对于它的价值,我使用经典的for循环,因为我发现它最容易阅读,理解,维护..


Other notes: 其他说明:

You should add some error checking that prevents the ++i version causing a crash if the last line of the file contains "Name" - currently the code will just increment past the end of the array and then try to access it, causing a crash. 您应该添加一些错误检查,以防止++i版本导致崩溃,如果文件的最后一行包含“名称” - 当前代码将只是递增超过数组的末尾,然后尝试访问它,导致崩溃。

Handling this could take the form of something as simple as running to i < Length - 1 so it stops on the second to last line 处理这个可以采取像运行到i < Length - 1这样简单的形式,因此它会在倒数第二行停止

Similarly the enumerator version would need protecting against this if the last line is a match for "Name" - I handled this by seeing if MoveNext() returned false 类似地,如果最后一行与“Name”匹配,则枚举器版本需要防止这种情况 - 我通过查看MoveNext()是否返回false来处理此问题


Strictly speaking you don't need to use a List<string> - File.ReadAllLines returns an array, and turning it to a list is a relatively expensive operation to perform if you don't need to. 严格来说,您不需要使用List<string> - File.ReadAllLines返回一个数组,如果您不需要,将其转换为列表是一项相对昂贵的操作。 If all you will do is iterate it or change the content of individual lines (but not add or remove lines), leave it as an array of string. 如果您要做的只是迭代它或更改单个行的内容(但不添加或删除行),请将其保留为字符串数组。 Using a List would make your life easier if you plan to manipulate it by inserting/removing lines though 如果您打算通过插入/删除线来操作它,那么使用List会让您的生活更轻松

You can implement FST ( F inite S tate M achine); 你可以实施FSTF inite S tate M achine); we have 2 states to consider: 我们有2州需要考虑:

  • 0 - line doesn't contain "Name" 0 - 行不包含"Name"
  • 1 - line contains "Name" 1 - 行包含"Name"

Code: 码:

if (args[0] == "prog1")
{
    int state = 0;

    // ReadLines - we don't have to read the entire file into a collection
    foreach (var line in File.ReadLines(filename)) {
      if (state == 0) {
        if (line.Contains("Name")) { 
          state = 1;

          Console.WriteLine(line); 
        }
      }
      else if (state == 1) {
        state = 0;

        Console.WriteLine(line); 
      }
    }
}
List<string> lines = File.ReadAllLines(filename).ToList();

for (int i = 0; i < lines.Count - 1; i++)
{
   if (lines[i].Contains("Name"))
   {
      Console.WriteLine(lines[i]);
      Console.WriteLine(lines[i + 1]);
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM