/// <summary> /// 给定若干个字符串和若干个正则表达式,生成若干个标注实例。 /// </summary> /// <param name="brush">用来确定标注类型的画笔类实例</param> /// <param name="inputs">给定字符串</param>\ /// <param name="patterns">正则表达式</param> /// <param name="fields">与正则表达式对应的字段</param> /// <param name="abort">提前终止条件</param> /// <param name="progress">进度报告</param> /// <returns>返回若干个标注实例</returns> /// <remarks> /// <para>生成规则(以单个字符串为例):</para> /// <para>1.按照标注类型的字段顺序,逐一和正则表达式相对应。字段数小于表达式数时,多余表达式忽略;字段数大于表达式数时,无表达式对应的字段始终为默认值。</para> /// <para>2.每个正则表达式多次提取,假设最终生成n个标注实例,则理论上每个正则都应匹配到1个或n个结果。</para> /// <para>3.若某个正则表达式匹配到1个结果,则n个标注实例的该字段都为该结果。</para> /// <para>4.若某个正则表达式匹配到1<x<n个结果,则前x个标注实例的该字段对应赋值,后(n-x)个标注实例该字段为空。</para> /// </remarks> private AnnotationBase[] GetAnnoFromRegex(BrushBase brush, string[] inputs, string[] patterns, FieldInfo[] fields = null, Process.Abort abort = null, IProgress <int> progress = null) { if (brush == null) { return(null); } if (fields == null) { fields = brush.AnnoType.GetFields(); } //所有有效的正则表达式产生的匹配结果(集合长度等同于有效字段个数) MatchCollection[] matches = new MatchCollection[Math.Min(fields.Length, patterns.Length)]; List <AnnotationBase> result = new List <AnnotationBase>(); foreach (string input in inputs) { if (abort != null && abort()) { return(null); } //正则匹配 int maxLength = 0; for (int i = 0; i < matches.Length; i++) { if (abort != null && abort()) { return(null); } if (patterns[i].Length <= 0) { continue; } matches[i] = Regex.Matches(input, patterns[i]); if (matches[i].Count > maxLength) { maxLength = matches[i].Count; } } for (int i = 0; i < maxLength; i++) { if (abort != null && abort()) { return(null); } object[] values = new object[fields.Length]; for (int j = 0; j < values.Length; j++) { if (j >= matches.Length || matches[j] == null) { continue; } if (i < matches[j].Count) { values[j] = matches[j][i].Value; } else if (matches[j].Count == 1) { values[j] = matches[j][0].Value; } } result.Add(brush.CreatAnnotation().SetFieldsValues(fields, values)); } if (progress != null) { progress.Report((Array.IndexOf(inputs, input) + 1) * 100 / inputs.Length); } } return(result.ToArray()); }
/// <summary> /// 计算正则表达式并写入textBox3中 /// </summary> /// <param name="abort"></param> private void CalRegex(Process.Abort abort) { try { if (textBox2.Text.Length > 0) { //显示的最大匹配数 const int max = 100; //报告相关 GlobalMessage.Add("status", "计算正则..."); string[] patterns = RegexText.GetLines(); MatchCollection matches = Regex.Matches(FileContext, patterns[0]); StringBuilder matchResult = new StringBuilder(""); int realCount = Math.Min(max, matches.Count); //报告相关 GlobalMessage.Progress progress = new GlobalMessage.Progress(realCount) { ProgressedString = matches.Count > max ? $"就绪 {realCount}/{matches.Count}个匹配项" : $"就绪 {matches.Count}个匹配项" }; if (matches.Count > max) { GlobalMessage.Add("info delay", $"匹配项过多,加载前{max}项"); } ListViewGroup[] groups = new ListViewGroup[realCount]; for (int i = 0; i < realCount; i++) { if (abort != null && abort()) { throw new Process.ProcessAbortException(); } matchResult.Append(matches[i].Value.Replace("\n", @"\n") + "\r\n"); FieldInfo[] fields = brushListPanel.CurrentItem.AnnoType.GetFields(FieldsOrder.BaseToSub); AnnotationBase[] annos = GetAnnoFromRegex(brushListPanel.CurrentItem, new string[1] { matches[i].Value }, patterns.SubArray(1, patterns.Length - 1), fields, abort); if (annos == null) { throw new Process.ProcessAbortException(); } ListViewGroup group = new ListViewGroup($"Match {i} ({annos.Length})"); foreach (AnnotationBase anno in annos) { object[] values = anno.GetFieldsValues(fields); group.Items.Add(new ListViewItem(values.ToStringArray())); } groups[i] = group; //报告相关 progress.Report(i + 1); } //报告相关 if (realCount == 0) { progress.Report(progress.MaxValue); } Invoke(new Action(() => { textBox3.Text = matchResult.ToString().Substring(0, Math.Min(textBox3.MaxLength, matchResult.Length)); listView1.Groups.AddRange(groups); foreach (ListViewGroup group in groups) { listView1.Items.AddRange(group.Items); } })); } else { GlobalMessage.Add("status", "就绪"); } } catch (Process.ProcessAbortException) { } catch (Exception ex) { GlobalMessage.Add("status", "正则计算错误"); GlobalMessage.Add("exception delay", ex.Message); } finally { GC.Collect(); } }