0

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

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+\*#)?)

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

有任何想法吗?

4

3 回答 3

1

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

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

替换正则表达式: (*#(\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());
    }
于 2012-12-11T23:38:44.887 回答
0

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

(\d+)\s+(?:(.*)(?:\s+\*#)|([^#]*))$
于 2012-12-11T23:37:22.407 回答
0

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

((\d+)\s+(.+?)(\s+\*#)*)
于 2012-12-11T23:50:10.420 回答