【问题标题】:Is it possible to use a Regular Expression to extract different blocks of text and multiple lines?是否可以使用正则表达式来提取不同的文本块和多行?
【发布时间】:2023-03-16 06:14:02
【问题描述】:

我想使用正则表达式从报告文档中提取不同的文本块 - 每个新页面在“FIRST NOTICE”前面都用 \x0c 表示 [未在下面显示]。我已经包含了一张带行号的图片以及文本,尽管格式可能是一个问题。

报告文本将包含 1..n 页 - 当数据返回时,每页都是单独的行项目。这些数据将被提取并转换为要输入数据库的行 [Number, Balance, Name, Address1, Address2, City, State, Zip]。

我需要提取的数据:

  1. 号码 - 11-1-11111-1
  2. 余额 - 1000.00
  3. 姓名 - “DOEN, JOHN THOMAS”[第 14 行,第 7-50 栏]
  4. 地址 - 2 到 3 行
  5. 进一步 - 分为 Addr1/Addr2/City/State/Zip
  6. 城市线:City ST Zip4 或 Zip-9
  7. 城市可能包含空格

数量和余额相对容易获得 - 这是我遇到最多问题的名称和地址部分,我正在寻找一个单一的正则表达式,它将把每个项目拉到自己的组中。

地址在第 15-17 行和第 7-50 列。

这可能吗?

包含两页的示例文档:

 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

【问题讨论】:

  • 是的,这是可能的。我在学习编程大约 2 年的时间里学习了正则表达式。每个人都应该学习它,而不是每次都问别人。一旦掌握了窍门,这并不难。
  • 这就是 Stack Overflow 的用途,而不是侮辱某人并假设他们“每次都在问别人”。我知道如何研究,并且有 - 并且无法找到这样的东西。我知道正则表达式,但在我看来,这是一个高级问题。如果您认为可行,请提供解决方案。
  • @AndreasMüller 一个荒谬的评论,所以开发人员可以互相帮助。用你的方法就不需要这个网站了!
  • @Matthew M. up/downvoting 取决于研究工作。我很欣赏您放置的样本,但我还看不到研究工作(您尝试过的正则表达式)。简单看一下,您的正则表达式必须类似于 FIRST NOTICE 空格(文本直到换行) NOTICE DATE...(日期)空格(字母数字直到换行)。在我看来不是很先进。您可以相信我,这并不是侮辱,而是作为一般说明 - 您可能没有注意到有多少人在 SO 上发布问题,而他们显然从未阅读过他们提出的任何问题。
  • @Jaycee 是的。所以他们可以互相帮助。不是这样他们就可以做别人的工作。通常你会在调试几天后看到我发布 SO 问题,这是我无法向自己解释的行为,或者直到我不知道要尝试什么。这就是要走的路,除非你想问相当简单的问题......

标签: c# regex


【解决方案1】:

正则表达式明确支持多行如下

Regex reg = new Regex(@"pattern1|pattern2", RegexOptions.Multiline);
var matches = reg.Matches("my text with /n lines");

Regex 的另一个方面是您可以将您的模式划分为段,这些段相当于要匹配的替代文本。请参阅vertical bar 上的这篇文章。使用从 reg.Matches 返回的 MatchCollection,您将能够提取数据。

我建议单独匹配名称和地址行,例如,如果您始终可以依赖字符串 ORIGINAL 与名称位于同一行的右侧,那么您可以单独编写正则表达式。正则表达式引擎将按顺序匹配模式,但您需要一些锚文本来清楚地搜索,然后获取相对于锚文本的值。然后,您需要解析并清除 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 个单独的模式,由 | 分割,这意味着交替。

您可以测试模式here,注意不要添加任何额外的字符,并确保检查多行和忽略大小写选项。

^ 在我们通过正则表达式构造函数使用多行模式时捕获一行的开头

[A-Z, ] 捕获 A-Z、逗号和空格

+ 重复出现前面的令牌 1 次或多次相当于说 {1,}

(?=original....) 在这种情况下预测模式original....hence(?=pattern)

The lookahead 不捕获字符,只是匹配。

其他模式类似,尽管最后一个匹配锚点之前的几个空行这是本页的结尾,并设置了某些字符的最小/最大出现次数{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();
        }
    }
}

【讨论】:

  • 它支持多行,理解 - 但是,我不知道如何告诉它提取名称/地址行。
  • @MatthewM。很公平,现在没有时间考虑正则表达式,但如果需要,可以稍后再看。
  • 是的,ORIGNAL/BLANACE/PAST DUE 一直都在,而且会在这些位置。我不认为我可以使用这些,尽管我在向前/向后看方面做得不多。我想没有锚的可选第三地址行可以锚定到“这是本页的结尾”?不过,不确定具体情况。
  • @MatthewM。如果它让你开始,我写了一篇博客文章,试图解释环视 - carndog.blogspot.co.uk/2014/02/regex-string-splitting.html - 它可能会让你开始。环视与括号字符有关(并搜索术语 And or Or
  • 你..是..太棒了!所以 - 非常感谢你。我刚刚完成了自己的版本.. (\d{2}-\d-\d{5}-\d)|ORIGINAL\.{5}:\s+?(.*)$ |(^\s{6}.*(?=ORIGINAL))|(\s{6}.*(?=BALANCE))|(\s{6}.*(?=PAST DUE))|(? :^\s{6}(.*)$(?=\n\n\这是本页的结尾))?我现在要比较两者。感谢您对前瞻/后视等的指示。我现在理解得更好了,事实上,这是理解的关键。你的博文和这个页面rexegg.com/regex-lookarounds.html 真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-31
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
相关资源
最近更新 更多