我必须使用以下示例结构解析文件
// This is a comment
// NotUsed : 123654
****************************************
* DESCRIPTION
***************************************
Header: xxx
Date: 20010101
ReqDate:20150402
P.O. 123456
Qty 10000
Part Number: xx-yy-456
Type: J
Product: xxyy123456V0.01 (bulk)
Cust ID: 51
Model:
Location: 60
UPC: 123456
*
cust_ref: Hello Worlkd
*
***************************************
* Data
***************************************
我确实尝试使用以下Regex,但是当没有使用冒号(:)时它没有捕获键/值
public class TestRegEx
{
private static readonly Regex KeyValFileRegex = new Regex(@"\b(?<key>(?!:)[\w\.]+|[ \w\.]+)\s*[\s=:]\s*(?<value>[^\n]*)(?=[^()\n]*[ =:\(]?)", RegexOptions.IgnoreCase);
private static int Main(string[] args)
{
string inputStr = @"// This is a comment
// NotUsed : 123654
****************************************
* DESCRIPTION
***************************************
Header: xxx
Date: 20010101
ReqDate:20150402
P.O. 123456
Qty 10000
Part Number: xx-yy-456
Type: J
Product: xxyy123456V0.01 (bulk)
Cust ID: 51
Model:
Location: 60
UPC: 123456
*
cust_ref: Hello Worlkd
*
***************************************
* Data
***************************************";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(inputStr));
using (var r = new StreamReader(stream))
{
var data = new Data();
string line;
while ((line = r.ReadLine()) != null)
{
var match = KeyValFileRegex.Match(line);
if (!match.Success) continue;
var key = match.Groups["key"].Value;
var value = match.Groups["value"].Value;
if (!string.IsNullOrEmpty(value)) value = value.Trim();
switch (key)
{
case "Header":
data.Header = value;
break;
case "ReqDate":
data.RequestedDeliveryDate = value;
break;
case "Qty":
data.Qty = Convert.ToInt32(value);
break;
case "Type":
data.Type = value;
break;
}
}
}
return 0;
}
private class Data
{
public string Header { set; get; }
public string RequestedDeliveryDate { set; get; }
public string Brand { set; get; }
public string Po { set; get; }
public int Qty { set; get; }
public string Type { set; get; }
}
}
非常感谢任何帮助。
答案 0 :(得分:0)
您当前的正则表达式存在缺陷,“Cust ID”字段将以“Cust”作为键返回,其余部分作为值返回。原因是正则表达式的[\s=:]
部分。它被配置为使用空格和冒号字符作为分隔符。
因此,即使使用当前的分隔符集,您也会遇到问题。现在,您可以在这些括号中添加任何其他内容,但是您添加的分隔符越多,您将遇到的问题就越多。您似乎不确定期望什么样的数据格式。
通常,您应该将regex配置为接受一个分隔符,而不是在同一个脚本中尝试所有分隔符。这是通过尝试使用一个脚本进行解析来完成的,如果没有给出结果,请尝试另一个脚本。当然,这是不好的做法,但如果你正在使用不可预测的数据,这是最简单的方法。
答案 1 :(得分:0)
您可以尝试另一种方法:如果有冒号,则匹配任意数量的空格,如果不匹配,则匹配至少3个空格 - 并使用该匹配来拆分字符串。看看:
public int Start()
{
var rxDelim = new Regex(@"(?(:):\s*|\s{3,})\s*");
var inputStr = @"// This is a comment
// NotUsed : 123654
****************************************
* DESCRIPTION
***************************************
Header: xxx
Date: 20010101
ReqDate:20150402
P.O. 123456
Qty 10000
Part Number: xx-yy-456
Type: J
Product: xxyy123456V0.01 (bulk)
Cust ID: 51
Model:
Location: 60
UPC: 123456
*
cust_ref: Hello Worlkd
*
***************************************
* Data
***************************************";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(inputStr));
var line = string.Empty;
using (var r = new StreamReader(stream))
{
var data = new Data();
var s = string.Empty;
while ((s = r.ReadLine()) != null)
{
if (Regex.IsMatch(s, @"(?i)^\*[^\r\n]*Description"))
{
s = r.ReadLine() + "\r\n";
line += s;
var add = r.ReadLine() + "\r\n";
while (add != null && !Regex.IsMatch(add, @"(?i)^\*[^\r\n]*Description"))
{
line += add + "\r\n";
add = r.ReadLine();
}
var matches = line.Split(new[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries).Select(p => rxDelim.Split(p).GetLength(0) > 1 && rxDelim.Split(p)[0] != "*" && !rxDelim.Split(p)[0].TrimStart(new[] { ' ' }).StartsWith("//") ?
new { Key = rxDelim.Split(p)[0], Value = rxDelim.Split(p)[1] } :
new { Key = string.Empty, Value = string.Empty });
foreach (var v in matches)
{
if (!String.IsNullOrWhiteSpace(v.Key) && !String.IsNullOrWhiteSpace(v.Value))
{
switch (v.Key)
{
case "Header":
data.Header = v.Value;
break;
case "ReqDate":
data.RequestedDeliveryDate = v.Value;
break;
case "Qty":
data.Qty = Convert.ToInt32(v.Value);
break;
case "Type":
data.Type = v.Value;
break;
}
}
}
}
}
}
return 0;
}