我使用正则表达式从收据中获取每个订单项的数据。 收据将如下所示:
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+\*#)?)
它不起作用,我认为这是因为使最后一个括号可选允许贪婪的(.*)
捕获绝对一切。如果最后一个括号不是可选的,那么正则表达式将为具有额外*#
的订单项执行其工作,但它与第一个和第三个不匹配(因为它们没有额外的{ {1}})。
有什么想法吗?
答案 0 :(得分: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());
}
答案 1 :(得分:0)
尝试使用此正则表达式(使用Multiline
选项):
(\d+)\s+(?:(.*)(?:\s+\*#)|([^#]*))$
答案 2 :(得分:0)
试一试。我认为它可以满足您的需求。
((\d+)\s+(.+?)(\s+\*#)*)