C# 正则表达式-根据条件捕获每一行

C# 正则表达式-根据条件捕获每一行,c#,regex,C#,Regex,回顾一年前我在这里遇到的一个解决方案: /* ----------------- jobnameA ----------------- */ insert_job: jobnameA job_type: CMD date_conditions: 0 alarm_if_fail: 1 /* ----------------- jobnameB ----------------- */ insert_job: jobnameB job_type: CMD date_condi

回顾一年前我在这里遇到的一个解决方案:

/* ----------------- jobnameA ----------------- */ 

insert_job: jobnameA   job_type: CMD 
date_conditions: 0
alarm_if_fail: 1


/* ----------------- jobnameB ----------------- */ 

insert_job: jobnameB   job_type: CMD 
date_conditions: 1
days_of_week: tu,we,th,fr,sa
condition: s(job1) & s(job2) & (v(variable1) = "Y" | s(job1)) & (v(variable2) = "Y" 
alarm_if_fail: 1
job_load: 1
priority: 10


/* ----------------- jobnameC ----------------- */ 
...
我使用以下正则表达式捕获每个作业,这些作业在其条件参数中使用了变量v(x)(此处仅jobnameB匹配):

现在,我需要在满足相同条件的情况下,将每一行捕获为参数组和值组

此正则表达式将获取每一行的参数和值作为单独的捕获组,但这不会考虑变量v(x)的存在,因此它会捕获所有作业:

(?:^([\w_]*\:) ([^\n]+))
下面的表达式将把我带到满意作业的第一行(insert_job),但它将在那里结束,而不是获取所有参数

(?:^[ \t]*/\*[\s-]*[\w-]*[\s-]*\*/)(?:(?!^[ \t]*/\*[\s-]*[\w-]*[\s-]*\*/).)*?(?:^([\w_]*\:) ([^\n]+))

任何进一步的帮助都将不胜感激。

我解析文本文件已有40多年了。如果我做不到,没有人能做到。我尝试了一段时间使用正则表达式分割“name:value”输入,但没有成功。所以我终于写了我自己的方法。看看我一周中的每一天都做了些什么

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.txt";
        static void Main(string[] args)
        {
            Job.Load(FILENAME);
        }
    }
    public class Job
    {
        public static List<Job> jobs = new List<Job>();

        public string name { get;set;}
        public string job_type { get;set;}
        public int date_conditions { get; set;}

        public DayOfWeek[] days_of_week { get; set; }
        public string condition { get; set; }

        public int alarm_if_fail { get; set; }
        public int job_load { get; set; }
        public int priority { get; set;}


        public static void Load(string filename)
        {
            Job newJob = null;
            StreamReader reader = new StreamReader(filename);
            string inputLine = "";
            while ((inputLine = reader.ReadLine()) != null)
            {
                inputLine = inputLine.Trim();
                if ((inputLine.Length > 0) && (!inputLine.StartsWith("/*")))
                {
                    List<KeyValuePair<string, string>> groups = GetGroups(inputLine);

                    foreach (KeyValuePair<string, string> group in groups)
                    {
                        switch (group.Key)
                        {
                            case "insert_job" :
                                newJob = new Job();
                                Job.jobs.Add(newJob);
                                newJob.name = group.Value;
                                break;

                            case "job_type":
                                newJob.job_type = group.Value;
                                break;

                            case "date_conditions":
                                newJob.date_conditions = int.Parse(group.Value);
                                break;

                            case "days_of_week":
                                List<string> d_of_w = new List<string>() { "su", "mo", "tu", "we", "th", "fr", "sa" };
                                newJob.days_of_week = group.Value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => (DayOfWeek)d_of_w.IndexOf(x)).ToArray();
                                break;

                            case "condition":
                                newJob.condition = group.Value;
                                break;

                            case "alarm_if_fail":
                                newJob.alarm_if_fail = int.Parse(group.Value);
                                break;

                            case "job_load":
                                newJob.job_load = int.Parse(group.Value);
                                break;

                            case "priority":
                                newJob.priority = int.Parse(group.Value);
                                break;

                        }
                    }
                }
            }

            reader.Close();
        }
        public static List<KeyValuePair<string, string>> GetGroups(string input)
        {
            List<KeyValuePair<string, string>> groups = new List<KeyValuePair<string, string>>();
            string inputLine = input;
            while(inputLine.Length > 0)
            {
                int lastColon = inputLine.LastIndexOf(":");
                string value = inputLine.Substring(lastColon + 1).Trim();
                int lastWordStart = inputLine.Substring(0, lastColon - 1).LastIndexOf(" ") + 1;
                string name = inputLine.Substring(lastWordStart, lastColon - lastWordStart);

                groups.Insert(0, new KeyValuePair<string,string>(name,value));
                inputLine = inputLine.Substring(0, lastWordStart).Trim();
            }
            return groups;
        }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.IO;
命名空间控制台应用程序1
{
班级计划
{
常量字符串文件名=@“c:\temp\test.txt”;
静态void Main(字符串[]参数)
{
Job.Load(文件名);
}
}
公开课工作
{
公共静态列表作业=新列表();
公共字符串名称{get;set;}
公共字符串作业类型{get;set;}
公共int日期_条件{get;set;}
公共星期日[]星期日{get;set;}
公共字符串条件{get;set;}
公共int报警如果失败{get;set;}
public int job_load{get;set;}
公共int优先级{get;set;}
公共静态无效加载(字符串文件名)
{
Job newJob=null;
StreamReader=新的StreamReader(文件名);
字符串inputLine=“”;
而((inputLine=reader.ReadLine())!=null)
{
inputLine=inputLine.Trim();
如果((inputLine.Length>0)和(!inputLine.StartsWith(“/*”))
{
列表组=GetGroups(inputLine);
foreach(组中的KeyValuePair组)
{
开关(组键)
{
案例“插入作业”:
newJob=新作业();
Job.jobs.Add(newJob);
newJob.name=group.Value;
打破
案例“工作类型”:
newJob.job_type=group.Value;
打破
案例“日期条件”:
newJob.date_conditions=int.Parse(group.Value);
打破
案例“每周天数”:
列表d_of w=新列表(){“su”、“mo”、“tu”、“we”、“th”、“fr”、“sa”};
newJob.days_of_week=group.Value.Split(新字符[]{',},StringSplitOptions.RemoveEmptyEntries)。选择(x=>(DayOfWeek)d_of_w.IndexOf(x)).ToArray();
打破
案例“条件”:
newJob.condition=group.Value;
打破
案例“故障报警”:
newJob.alarm\u if\u fail=int.Parse(group.Value);
打破
案例“工作负载”:
newJob.job\u load=int.Parse(group.Value);
打破
案例“优先权”:
newJob.priority=int.Parse(group.Value);
打破
}
}
}
}
reader.Close();
}
公共静态列表GetGroups(字符串输入)
{
列表组=新列表();
字符串inputLine=输入;
while(inputLine.Length>0)
{
int lastColon=inputLine.LastIndexOf(“:”);
字符串值=inputLine.Substring(lastColon+1.Trim();
int lastWordStart=inputLine.Substring(0,lastColon-1).LastIndexOf(“”+1;
string name=inputLine.Substring(lastWordStart,lastColon-lastWordStart);
插入(0,新的KeyValuePair(名称、值));
inputLine=inputLine.Substring(0,lastWordStart.Trim();
}
返回组;
}
}
}

我想如果你把它分成几个步骤,这会容易得多。我使用LINQ实现以下目的:

var jobsWithVx = Regex.Matches(src, @"(?ms)(^[ \t]*/\*[\s-]*([\w-]*)[\s-]*\*/)((?:(?:(?!^[ \t]*/\*[\s-]*[\w-]*[\s-]*\*/).)*?condition\: ([^\n\r]*v\([^\n\r]*)[ \t]*\))+(?:(?!^[ \t]*/\*[\s-]*[\w-]*[\s-]*\*/).)*)").Cast<Match>().Select(m => m.Value);

var jobParameters = jobsWithVx.Select(j => Regex.Matches(j, @"(?ms)^([\w_]+\:) (.+?)$")).Select(m => m.Cast<Match>().Select(am => am.Groups));
在LINQPad中运行的示例:

var src = @"/* ----------------- jobnameA ----------------- */ 

insert_job: jobnameA   job_type: CMD 
date_conditions: 0
alarm_if_fail: 1


/* ----------------- jobnameB ----------------- */ 

insert_job: jobnameB   job_type: CMD 
date_conditions: 1
days_of_week: tu,we,th,fr,sa
condition: s(job1) & s(job2) & (v(variable1) = ""Y"" | s(job1)) & (v(variable2) = ""Y"" 
alarm_if_fail: 1
job_load: 1
priority: 10


/* ----------------- jobnameC ----------------- */
";

var jobsWithVx = Regex.Matches(src, @"(?ms)(^[ \t]*/\*[\s-]*([\w-]*)[\s-]*\*/)((?:(?:(?!^[ \t]*/\*[\s-]*[\w-]*[\s-]*\*/).)*?condition\: ([^\n\r]*v\([^\n\r]*)[ \t]*\))+(?:(?!^[ \t]*/\*[\s-]*[\w-]*[\s-]*\*/).)*)").Cast<Match>().Select(m => m.Value);

var jobParameters = jobsWithVx.Select(j => Regex.Matches(j, @"(?ms)^([\w_]+\:) (.+?)$")).Select(m => m.Cast<Match>().Select(am => am.Groups));
jobParameters.Dump();
var src=@/*------------jobnameA--------------------------/
插入作业:作业名称作业类型:CMD
日期和条件:0
故障时报警:1
/*----------------工作名称B--------------------------*/
插入作业:作业名称b作业类型:CMD
日期和条件:1
一周的天数:tu、we、th、fr、sa
条件:s(job1)&s(job2)&(v(variable1)=“Y”| s(job1))&(v(variable2)=“Y”
故障时报警:1
工作负荷:1
优先事项:10
/*---------工作名称C--------*/
";
var jobsWithVx=Regex.Matches(src,@“(?ms)(^[\t]*/\*[\s-]*([\w-]*)[\s-]**/)(((?:(?:(?:(?:(?!^[\t]*/\[\s-]*[\w-[\s-]*/)*)*?条件\:([^\n\r]*v\[^\n\n\r]*)[\t]+++++(?:(?:(?:(!!^-[\t]*[\t]*]/*.[\s-*])。选择m-*.[*]);
var jobParameters=jobsWithVx.Select(j=>Regex.Matches(j,@“(?ms)^([\w\u]+\:)(.+?)$”))。Select(m=>m.Cast().Select(am=>am.Groups));
jobParameters.Dump();

您是否考虑逐行解析文件中的输入读数并在开始时看到代码< > /*-/COD>填写条目?一个单一的正则表达式来解析这些似乎是低效的。
foreach (var aJobsParms in jobParameters) {
    foreach (var jobParm in aJobsParms) {
        // work with job and parm
    }
    // alternatively, convert to a Dictionary
    var jobDict = aJobsParms.ToDictionary(jpgc => jpgc[1].Value, jpgc => jpgc[2].Value));
    // then work with the dictionary
}
var src = @"/* ----------------- jobnameA ----------------- */ 

insert_job: jobnameA   job_type: CMD 
date_conditions: 0
alarm_if_fail: 1


/* ----------------- jobnameB ----------------- */ 

insert_job: jobnameB   job_type: CMD 
date_conditions: 1
days_of_week: tu,we,th,fr,sa
condition: s(job1) & s(job2) & (v(variable1) = ""Y"" | s(job1)) & (v(variable2) = ""Y"" 
alarm_if_fail: 1
job_load: 1
priority: 10


/* ----------------- jobnameC ----------------- */
";

var jobsWithVx = Regex.Matches(src, @"(?ms)(^[ \t]*/\*[\s-]*([\w-]*)[\s-]*\*/)((?:(?:(?!^[ \t]*/\*[\s-]*[\w-]*[\s-]*\*/).)*?condition\: ([^\n\r]*v\([^\n\r]*)[ \t]*\))+(?:(?!^[ \t]*/\*[\s-]*[\w-]*[\s-]*\*/).)*)").Cast<Match>().Select(m => m.Value);

var jobParameters = jobsWithVx.Select(j => Regex.Matches(j, @"(?ms)^([\w_]+\:) (.+?)$")).Select(m => m.Cast<Match>().Select(am => am.Groups));
jobParameters.Dump();