【发布时间】:2020-02-01 20:24:32
【问题描述】:
所以我用 C# 制作了一个控制台应用程序,它将读取电子邮件并从中提取数据。
在一些帮助下,我已经将它带到了一个可以成对读取列的阶段,但是一旦我到达电子邮件的底部(可能比这两行还要多),它就无法将其分解。
这是我尝试过的:
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
namespace Multiline_Email_Test
{
// <summary>
/// Console app to test the reading of the multiline email.
/// If successful readback is shown we could import to SQL Server.
/// </summary>
public class Program
{
public static void Main()
{
string email = @"NOTIFICATION OF MOVEMENT STARTING IN AUGUST
Consignor Package ID Local Reference Number
------------------- ----------------------
GRLK123450012 123456
Place Of dispatch Guarantor type code
----------------- -------------------
GR00001234567 1
Consignee Package ID Guarantor details
----------------- -------------------
RR001239E0070
Place Of delivery Date of dispatch DD MM YYYY
----------------- ---------------------------
FR001379E0570 21 03 2019
Time of dispatch
----------------
08:29
Vehicle registration number
---------------------------
XXBB12345678
Item number Package Product CN CodeCode Quantity Brand
----------- ------------------------- -------- -----
Line 1 of 2 B000 22040009 7603.200 Guinness DIC 440ml CAN 06X04 MDCES
Line 2 of 2 B000 22040009 14636.160 Guinness DIC 440ml CAN 06X04 MDCES
";
var dict = new Dictionary<string, string>();
try
{
var lines = email.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
int starts = 0, end = 0, length = 0;
while (!lines[starts + 1].StartsWith("-"))
starts++;
for (int i = starts + 1; i < lines.Length; i += 3)
{
var mc = Regex.Matches(lines[i], @"(?:^| )-");
foreach (Match m in mc)
{
int start = m.Value.StartsWith(" ") ? m.Index + 1 : m.Index;
end = start;
while (lines[i][end++] == '-' && end < lines[i].Length)
;
length = Math.Min(end - start, lines[i - 1].Length - start);
string key = length > 0 ? lines[i - 1].Substring(start, length).Trim() : "";
end = start;
while (lines[i][end++] == '-' && end < lines[i].Length)
;
length = Math.Min(end - start, lines[i + 1].Length - start);
string value = length > 0 ? lines[i + 1].Substring(start, length).Trim() : "";
dict.Add(key, value);
}
}
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
foreach (var x in dict)
Console.WriteLine("{0} : {1}", x.Key, x.Value);
}
}
}
我在这里用 .net fiddle 创建了一个现场演示 https://dotnetfiddle.net/6nMO2c
【问题讨论】:
-
您的代码完全按照您的要求执行。您只能读取虚线下方的值,而底线不是,因此不会读取。如果你想理解这封电子邮件,你需要一个不同的策略。
-
如何让它匹配“项目编号”并以不同的方式读取六列?
-
我认为需要更多信息。是否可以读取固定列?标题和虚线无论如何都不适合。 “麸皮”被严重截断,并且标题中不存在大肠杆菌(我认为是)列。
-
当然,标题可以移动,因此固定列是不可能的,如果数据较长,则会出现从左到右的截断和移动,这就是为什么我认为 Regex Match 无论如何都会找到它的原因。
-
注意。你确定
Dictionary<string, string>是正确的数据结构吗?第一个项目行的数据不会被第二个项目行的数据覆盖吗?也许考虑List<KeyValuePair<string, string>>?