【问题标题】:Get data from receipt using regular expressions使用正则表达式从收据中获取数据
【发布时间】:2012-12-11 23:28:27
【问题描述】:

我正在使用正则表达式从收据中获取每个行项目的数据。 收据将如下所示:

Qty Desc
1   JD *#
    MARTINI *#   
2   XXXXXX 
3   YYYYYY
4   JD
    PEPSI *#

所有项目都有数量和描述,其中一些有额外的*#。另外,请注意,描述中可以有空格,甚至不止一行,每一行都可以有自己的*#。我想抓住数量和描述(如果多于一行,则获取所有行),我根本不在乎额外的*#。所以在这个例子中,对于第一个行项目,我会捕获 Quantity=1 和 Description="JD MARTINI"。第四个,Quantity=4,Description="JD PEPSI"。

我当前的正则表达式如下所示:

((\d+)\s+(.*)(\s+\*#)?)

它不起作用,我认为这是因为将最后一个括号设为可选允许贪婪的(.*) 绝对捕获所有内容。如果最后一个括号不是可选的,则正则表达式将对带有额外 *# 的行项目执行其工作,但它不会匹配第一个和第三个括号(因为它们没有额外的 *# )。

有什么想法吗?

【问题讨论】:

  • 你的描述都是纯文本,还是有空格?
  • @Ann L - 干得好,我只是想问这个:-)
  • 您可能想在 regexlib.com 上尝试正则表达式测试工具,顺便说一句。我发现它很有帮助。
  • 很抱歉忘记提及这一点。它们确实有空格。

标签: c# .net regex string split


【解决方案1】:

在阅读了您修改后的问题后,我确定您希望完成的事情不能用一个正则表达式来完成。你将不得不做正则表达式匹配+替换的组合。 (看这个问题:Regular expression to skip character in capture group

匹配正则表达式:(\d+)\s+([A-Z\s*#]*[A-Z]+)

替换正则表达式:(*#(\s*))|(\r\n\s+)(?=\s)

匹配正则表达式将匹配数量和项目描述,包括任何中间换行符或 *# 出现,省略最后的 *#。我假设描述中的最后一个字符是一个字母。

运行匹配正则表达式后,您将得到一个匹配数组,您需要对其进行迭代以转换为对象。我写了一些方便的代码来为你做这件事。对于每个对象,您将对对象的描述运行替换正则表达式,这将删除无关的空格和 *#。

     class ReceiptItem
    {
        public int Quantity { get; set; }
        public string Description { get; set; }

        public override string ToString()
        {
            return string.Format("{0}\t{1}", Quantity, Description);
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var matches = Regex.Matches(textBox1.Text, @"(\d+)\s+([A-Z\s\*\#]*[A-Z]+)", RegexOptions.Multiline);
        var items = (from Match m in matches
                     select new ReceiptItem()
                                {
                                    Quantity = int.Parse(m.Groups[1].Value),
                                    Description = Regex.Replace(m.Groups[2].Value, @"(\*\#(\s*))|(\r\n\s+)(?=\s)", "")
                                });

        listBox1.Items.AddRange(items.ToArray());
    }

【讨论】:

  • 它并不能完全满足我的需求,但我没有给出一个更好、更解释的例子来说明我想要完成的事情是我的错。请查看已编辑的问题。
  • 出色的工作和完美的解释。谢谢!
【解决方案2】:

试试这个正则表达式(带有Multiline 选项):

(\d+)\s+(?:(.*)(?:\s+\*#)|([^#]*))$

【讨论】:

  • 可能是因为我正在使用正则表达式教练,但它不匹配任何东西。
  • 我在这个页面上试过了:derekslager.com/blog/posts/2007/09/…
  • 它在 Regex Coach 中匹配。你检查了多行框吗?
  • 如果你使用这个作为目标字符串:“1 示例一\n\n1 示例二 *#\n 测试 1 *#\n1 示例三 *#\n测试 2 *#”,它不会匹配“1 Example 2 *#”,它会用“1 Example One”捕获一些额外的空格。
【解决方案3】:

试试这个。我认为它可以满足您的需求。

((\d+)\s+(.+?)(\s+\*#)*)

【讨论】:

  • 它只获取每个订单项描述的第一个字符。
猜你喜欢
  • 1970-01-01
  • 2013-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-27
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多