.NET 正则表达式,用于使用分量计解析文件

本文关键字:文件 分量 正则表达式 用于 NET | 更新日期: 2024-11-08 04:34:57

我必须使用以下示例结构解析文件

// 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
***************************************

我确实尝试使用以下正则表达式,但是当冒号(:)未使用

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; }
    }
}

任何帮助将不胜感激。

.NET 正则表达式,用于使用分量计解析文件

您当前的正则表达式存在缺陷,返回"Cust ID"字段,其中"Cust"作为键,其余部分作为值。原因是正则表达式的['s=:]部分。它配置为同时使用空格和冒号字符作为分隔符。

因此,即使使用当前的分隔符集,您也有问题。现在,您可以将其他任何内容放在这些括号中,但是您添加到其中的分隔符越多,您会遇到的问题就越多。您似乎不确定需要哪种数据格式。

通常,您应该将正则表达式配置为接受其中一个分隔符,而不是在同一脚本中尝试所有分隔符。这是通过尝试使用一个脚本解析来完成的,如果没有给出结果,请尝试另一个脚本。当然,这是不好的做法,但如果您正在处理不可预测的数据,这是最简单的方法。

您可以尝试另一种方法:如果有冒号,请匹配任意数量的空格,如果没有,则至少匹配 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;
}