在分隔符之间提取文本行,并将它们添加到List <string>

时间:2015-08-25 12:29:09

标签: c# regex list parsing text

我有一个文本文件,其中包含我要提取的分隔符之间的一些数字,并将它们添加到两个不同的列表中。我要填充的列表是:

points = new List<string>();
coords = new List<string>();

这是输入文件的样子:

blah
blah
    point   [
         0 50 50,
         50 50 50,
         50 0 50,
         0 0 50,
        ]
blah
blah
coordIndex [
 3,2,0,-1,
 2,1,0,-1,
]
blah
blah

blah
blah
    point   [
         0 50 0,
         50 50 0,
         50 0 0,
         0 0 0,
        ]
blah
blah
coordIndex [
 3,0,2,-1,
 0,1,2,-1,
]
blah
blah

我想要做的是按照以下逻辑获取数字(包括逗号):

  1. 获取关键字“point [”和下一个“]”之间的界限。每一行都是一个“字符串”。

    将这些行添加到列表“points”

  2. 获取关键字“coordIndex [”和下一个“]”之间的界限。每一行都是一个“字符串”。

    将这些行添加到“coords”列表

  3. 到目前为止,我只是设法摆脱空白区域以“获取”点数字段,但我不知道如何填充列表。

    有人可以帮忙吗?我很乐意使用正则表达式或其他任何选项。

    代码

    using System;
    using System.IO;
    using System.Collections.Generic;
    using System.Text.RegularExpressions;
    using System.Linq;
    
    namespace parsing
    {
        class Program
        {
            static void Main(string[] args)
            {
                string inputFile = "Q:/inputFile.txt";
    
                //Lists to be populated
                var points = new List<string>();
                var coords = new List<string>();
    
                //Parsing the file
                using (StreamReader readInputFile = new StreamReader(inputFile))
                {
    
                    string line;
                    while ((line = readInputFile.ReadLine()) != null)
                    {
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            //Remove tabs
                            string line_noTabs = line.Replace("\t", "");
    
                            //Get lines between the keywords "point [" and the next "]". Each line is a "string".
                                //Add these lines to a the list "points"
    
                            //Get lines between the keywords "coordIndex [" and the next "]". Each line is a "string".
                                //Add these lines to a the list "coords"
                        }
    
                    }
                }
    
            }//end main
        }//end program
    }//end namespace
    

4 个答案:

答案 0 :(得分:1)

您只需要遍历文件,一次一行并设置一系列标记,然后您可以稍后检查以查看文件的哪个块。

然后,您将检查标记以查看添加项目所需的列表。

您的代码需要看起来像这样:

using (StreamReader readInputFile = new StreamReader(inputFile))
{

    string line;
    bool isPoint = false;
    bool isCoord = false;
    Regex pointRegex = new Regex("point\\s+\\[");
    Regex coordRegex = new Regex("coordIndex\\s+\\[");
    Regex endBrace = new Regex("\\s*\\]\\s*");

    while ((line = readInputFile.ReadLine()) != null)
    {
        if (!string.IsNullOrWhiteSpace(line))
        {
            //Remove tabs
            string line_noTabs = line.Replace("\t", "");
            if(pointRegex.IsMatch(line_noTabs))
            {
                isPoint = true;
                continue;
            }
            else if(coordRegex.IsMatch(line_noTabs))
            {
                isCoord = true;
                continue;
            }
            else if (endBrace.IsMatch(line_noTabs))
            {
                isPoint = false;    //Reset
                isCoord = false;    //Reset
                continue;
            }

            if(isPoint)
                points.Add(line_noTabs);
            else if(isCoord)
                coords.Add(line_noTabs);
        }
    }
}

答案 1 :(得分:0)

这是一种方法:

  1. 使用\[([^\]]+)]获取括号(https://regex101.com/r/sG4zO1/1)之间的所有内容。
  2. 对于每个正则表达式结果,使用regexResult.Split(new char[0], StringSplitOptions.RemoveEmptyEntries)在括号内获取一组数字。
  3. 循环使用正则表达式结果,知道:
    • 如果index % 2 == 0,那么您正在查看point
    • 如果index % 2 == 1,那么您有coordIndex个值

答案 2 :(得分:0)

如果您希望将每个 point \ coordIndex 批次中的每一行作为Item中的新List批处理,那么请使用(\d+\s\d+\s\d+)|(\d,\d,\d,-?\d,)这样的正则表达式你会得到两组匹配 - 一组用于积分,一组用于coordIndexes(这取决于你给出的例子,如果数据可以变化,则必须改进正则表达式。)

如果稍后您需要使用 point \ coordIndex 字符串中的数字,则需要应用一些c#来“解析”字符串。

答案 3 :(得分:0)

试试这个。我将您的列表更改为整数。我起诉了Regex,但可以轻松地将代码更改为类似于代码的方法

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"C:\temp\test.txt";
        static void Main(string[] args)
        {
            string input = File.ReadAllText(FILENAME);
            string pattern = @"(?'type'\w+)\s+\[(?'array'[^\]]+)\]";
            Regex expr = new Regex(pattern, RegexOptions.Singleline);
            MatchCollection matches = expr.Matches(input);


            //Lists to be populated
            List<List<int>> points = new List<List<int>>();
            List<List<int>> coords = new List<List<int>>();


            foreach (Match match in matches)
            {

                string type = match.Groups["type"].Value;
                string strArray = match.Groups["array"].Value;
                StringReader reader = new StringReader(strArray);
                string line = "";
                while ((line = reader.ReadLine()) != null)
                {
                    line = line.Trim();
                    if (line.Length > 0)
                    {
                        List<int> intArray = line.Split(new char[] { ',', ' '}, StringSplitOptions.RemoveEmptyEntries).Select(x => int.Parse(x)).ToList();
                        switch (type)
                        {
                            case "point":
                                points.Add(intArray);
                                break;
                            case "coordIndex":
                                coords.Add(intArray);
                                break;
                        }
                    }
                }
            }

        }
    }
}
​