我需要通过捕获元素之间存在的内容来从电子邮件表单中捕获表单数据文本。
我在电子邮件正文中得到的文字是多行的,关键字之间有很多空格。我不在乎空白;我会修剪它,但我必须能够捕获两个表单字段描述符之间发生的事情。
关键短语非常清晰且独特,但我无法使正则表达式工作:
示例数据:
Loan Number:
123456789
Address:
101 Main Street
My City, WA
99101
Servicemember Name:
Joe Smith
Servicemember Phone Number:
423-283-5000
Complaint Description:
He has a complaint
Associate Information
Associate Name:
Some Dude
Phone Login:
654312
Complaint Date:
1/10/2012
正则表达式(例如,捕获贷款号码):
^Loan Number:(.*?)Address:.$
我缺少什么>?
编辑:此外,除了在各种表单标签之间捕获数据之外,我还需要捕获最后一个标签和文件末尾之间的数据。在阅读了这里的回复之后,我已经能够捕获表单标签之间的数据,而不是最后一段数据,即投诉日期。
答案 0 :(得分:2)
我错过了什么?
您需要删除锚点(^
和$
)并启用 dotall ,以允许.
匹配新行。对C#不太熟悉,但它应该是m
修饰符。 Check the docs
为什么这么难?
正则表达式是一个非常强大的工具。 强大的力量带来了巨大的责任。也就是说,没有人说这很容易......
在仔细检查问题之后,你有坚实的锚点和非常具体的捕获(即贷款号码数字。以下正则表达式应该有效,并且没有提到的修饰语。
Loan Number\s+(\d+)\s+Escalation Required
答案 1 :(得分:0)
这个适用于我:
Loan Number(?<Number>(.*\n)+)Escalation Required
其中Number为命名组是结果。
答案 2 :(得分:0)
您的主要问题是您没有指定Multiline
模式。没有它,^
只匹配文本的开头,而$
只匹配最后一个。此外,(.*?)
除了数字本身之外,还需要匹配贷款号码之前和之后的行分隔符,除非您指定Singleline
模式,否则它不能这样做。
您可以通过两种方式指定这些匹配模式。一种是在创建正则表达式时传递适当的RegexOptions
参数:
Regex r = new Regex(@"^Loan Number(.*?)Escalation Required.$",
RegexOptions.Multiline | RegexOptions.Singleline);
另一种方法是在正则表达式中添加“内联”修饰符:
Regex r = new Regex(@"(?ms)^Loan Number(.*?)Escalation Required.$");
但我建议你这样做:
Regex r = new Regex(@"(?m)^Loan Number\s*(\d+)\s*Escalation Required(?=\z|\r\n|[\r\n])");
关于\s*(\d+)\s*
:
在单线模式(在某些版本中称为DOTALL模式)中,没有什么可以阻止.*?
一直匹配到文档的末尾,无论它多么恰好。由于非贪婪的修饰符(?
),它将尝试尽可能少地消耗,但是在不可能匹配的情况下,正则表达式引擎必须做很多事情。在承认失败之前毫无意义的工作。因此我几乎从不使用单线模式。
单线模式与否,请勿使用.*
或.*?
,至少不要考虑更具体的内容。在这种情况下,\s*(\d+)\s*
的优势在于它允许您仅捕获贷款号 。您不必修剪空格或执行任何其他操作来提取您感兴趣的部分。
关于(?=\z|\r\n|[\r\n])
:
根据{{3}},多行模式中的$
应该在回车(\r
)之前或换行符(\n
之前)匹配,如果前面没有{{1} - 它永远不应与 \r
和\r
之间的匹配。还有其他几个单字符行分隔符,但.NET正则表达式除了\n
之外不能识别任何内容。您的源文本(电子邮件)使用\n
来分隔行,这就是您必须在锚点之前添加该点的原因:\r\n
。
但是,如果您不知道期望哪种线分隔符怎么办?实际上,.$
或\n
是迄今为止最常见的选择,但即使您忽视其他选项,\r\n
也会失败一半。 .$
仍然是一个黑客,但它是一个更多的便携式黑客。 ;)它甚至处理(?=\z|\r\n|[\r\n])
(仅回车)与OSX之前的Macintosh系统相关联的行分隔符。