C# 是否可以使用正则表达式提取不同的文本块和多行?
我想使用正则表达式从报表文档中提取不同的文本块-每个新页面在“FIRST NOTICE”(第一个通知)前面用\x0c表示[下面未显示]。我已经包括了一张带有行号的图片和文本,尽管格式可能有问题 报告文本将包含1..n页-返回数据时,每一页都是单独的行项目。这些数据将被提取并转换成行,输入数据库[编号、余额、名称、地址1、地址2、城市、州、邮政编码] 我需要提取的数据片段:C# 是否可以使用正则表达式提取不同的文本块和多行?,c#,regex,C#,Regex,我想使用正则表达式从报表文档中提取不同的文本块-每个新页面在“FIRST NOTICE”(第一个通知)前面用\x0c表示[下面未显示]。我已经包括了一张带有行号的图片和文本,尽管格式可能有问题 报告文本将包含1..n页-返回数据时,每一页都是单独的行项目。这些数据将被提取并转换成行,输入数据库[编号、余额、名称、地址1、地址2、城市、州、邮政编码] 我需要提取的数据片段: 编号-11-1-11111-1 余额-1000.00 名称-“多恩,约翰·托马斯”[第14行,第7-50列] 地址-2至3行
正则表达式显式支持多行,如下所示
Regex reg = new Regex(@"pattern1|pattern2", RegexOptions.Multiline);
var matches = reg.Matches("my text with /n lines");
Regex的另一个方面是,您可以将模式划分为相当于要匹配的备用文本的段。请参阅上的这篇文章。使用从reg.Matches返回的MatchCollection,您将能够提取数据
我建议分别在名称行和地址行上进行匹配,例如,如果您可以始终依赖于与名称位于同一行右侧的字符串,那么您可以分别为此编写正则表达式。正则表达式引擎将按顺序匹配模式,但您需要一些锚文本来清晰地搜索,然后获取相对于锚文本的值。然后需要解析并清除Match对象返回的值
更新
我之前的回答被部分编辑以删除无关信息
下面是一个包含解决方案的程序,正则表达式相对简单,因此我将为那些不熟悉第一个模式语法的人详细介绍:
^[A-Z, ]+(?=original...)|^[A-Z, 0-9]+(?=balance...)|^[//A-Z, 0-9]+(?=past due...)|^[^\n\.]{2,50}(?=\n\s+\n^\s+THIS IS THE END OF THIS PAGE)
正则表达式包含由|
分割的4个独立模式,这意味着交替
您可以小心地测试模式,不要添加任何额外字符,并确保选中多行和忽略大小写选项
^
通过正则表达式构造函数使用多行模式时捕获行的开头
[A-Z,]
捕获A-Z、逗号和空格
+
重复前面标记的出现1次或多次,相当于说{1,}
(?=original…)
在本例中查找模式original…
因此(?=pattern)
不捕获字符,只捕获匹配项
其他模式类似,但最后一个模式与锚之前的两个空行相匹配。这是本页的结尾,并在某些字符上设置最小/最大出现次数{2,50}
C#清理返回的令牌的示例-名称和地址-示例数据的7项
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace RegexTester
{
class Program
{
static string text = @"FIRST NOTICE COMPANYNAME
NOTICE DATE....: 01/01/2001 1111 N NORTHWOOD DR
NUMBER.........: 11-1-11111-1 SOMEWHERE WY 05920-5929
THE DATE.......: 02/01/2001
Some data only.
DOEN, JOHN THOMAS ORIGINAL....: 5789.00
1111 N WALT AVE BALANCE.....: 1000.00
C/O SOMEONE ELSE PAST DUE....: 500.00
SOMEWHERE WY 04741-5555
THIS IS THE END OF THIS PAGE DATE DUE: 02/01/2001
FIRST NOTICE COMPANYNAME
NOTICE DATE....: 01/01/2001 1111 N NORTHWOOD DR
NUMBER.........: 22-2-22222-2 SOMEWHERE WY 05920-5929
THE DATE.......: 02/01/2001
Some data only.
DOE, JOHNAT ZOAR ORIGINAL....: 2211.00
11111 N DIVISOR RD BALANCE.....: 2000.00
SOMWEHERE WY 05922 PAST DUE....: 1000.00
THIS IS THE END OF THIS PAGE DATE DUE: 02/01/2001";
static void Main(string[] args)
{
string pattern = @"^[A-Z, ]+(?=original...)|^[A-Z, 0-9]+(?=balance...)|^[//A-Z, 0-9]+(?=past due...)|^[^\n\.]{2,50}(?=\n\s+\n^\s+THIS IS THE END OF THIS PAGE)";
Regex regex = new Regex(pattern, RegexOptions.Multiline | RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(text);
List<string> cleaned = matches.Cast<Match>().Select(x => x.Value.Trim()).ToList();
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Text.RegularExpressions;
名称空间RegexTester
{
班级计划
{
静态字符串text=@“第一个通知公司名称”
通知日期:2001年1月1日北纬1111诺思伍德博士
编号:11-1-11111-1 WY 05920-5929
日期:2001年1月2日
只有一些数据。
多恩,约翰·托马斯原件:5789.00
华尔特大道1111号余额……:1000.00
转交其他逾期未付的人….:500.00
WY 04741-5555某处
本页到此结束日期截止日期:2001年1月2日
第一通知公司名称
通知日期:2001年1月1日北纬1111诺思伍德博士
编号:22-2-22222-2 WY 05920-5929
日期:2001年1月2日
只有一些数据。
能源部,约翰纳特·佐尔原版….:2211.00
11111 N除数RD余额…:2000.00
索姆韦赫WY 05922逾期….:1000.00
这是本页的结尾日期截止日期:2001年1月2日”;
静态void Main(字符串[]参数)
{
字符串模式=@“^[A-Z,]+(?=原始…)^[A-Z,0-9]+(?=余额…)^[///A-Z,0-9]+(?=过期…)^[^\n\.]{2,50}(?=\n\s+\n^\s+这是本页的结尾)”;
Regex Regex=new Regex(模式,RegexOptions.Multiline | RegexOptions.IgnoreCase);
MatchCollection matches=regex.matches(文本);
List=matches.Cast().Select(x=>x.Value.Trim()).ToList();
}
}
}
它支持多行,理解-但是,我不知道如何告诉它提取姓名/地址行。@MatthewM。公平地说,现在没有时间考虑正则表达式,但如果需要,可以稍后再查看。是的,原始/BLANACE/过期总是存在,并且将处于这些位置。我不认为我可以使用这些,虽然我没有做太多的前瞻性/落后。我想可选的没有锚定的第三个地址行可以锚定到“THIS IS the END OF THIS PAGE”?不过,我还是不确定具体细节。@MatthewM。如果它能让你开始,我写了一篇博文,试图解释“环顾四周”——它可能会让你开始。查找与括号字符有关(并搜索术语和/或或你..是..太棒了!非常感谢。我刚刚完成了自己的版本..(\d{2}-\d)-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace RegexTester
{
class Program
{
static string text = @"FIRST NOTICE COMPANYNAME
NOTICE DATE....: 01/01/2001 1111 N NORTHWOOD DR
NUMBER.........: 11-1-11111-1 SOMEWHERE WY 05920-5929
THE DATE.......: 02/01/2001
Some data only.
DOEN, JOHN THOMAS ORIGINAL....: 5789.00
1111 N WALT AVE BALANCE.....: 1000.00
C/O SOMEONE ELSE PAST DUE....: 500.00
SOMEWHERE WY 04741-5555
THIS IS THE END OF THIS PAGE DATE DUE: 02/01/2001
FIRST NOTICE COMPANYNAME
NOTICE DATE....: 01/01/2001 1111 N NORTHWOOD DR
NUMBER.........: 22-2-22222-2 SOMEWHERE WY 05920-5929
THE DATE.......: 02/01/2001
Some data only.
DOE, JOHNAT ZOAR ORIGINAL....: 2211.00
11111 N DIVISOR RD BALANCE.....: 2000.00
SOMWEHERE WY 05922 PAST DUE....: 1000.00
THIS IS THE END OF THIS PAGE DATE DUE: 02/01/2001";
static void Main(string[] args)
{
string pattern = @"^[A-Z, ]+(?=original...)|^[A-Z, 0-9]+(?=balance...)|^[//A-Z, 0-9]+(?=past due...)|^[^\n\.]{2,50}(?=\n\s+\n^\s+THIS IS THE END OF THIS PAGE)";
Regex regex = new Regex(pattern, RegexOptions.Multiline | RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(text);
List<string> cleaned = matches.Cast<Match>().Select(x => x.Value.Trim()).ToList();
}
}
}