Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用delimeters解析文件的.NET正则表达式_C#_.net_Regex - Fatal编程技术网

C# 用delimeters解析文件的.NET正则表达式

C# 用delimeters解析文件的.NET正则表达式,c#,.net,regex,C#,.net,Regex,我必须使用以下示例结构解析文件 // This is a comment // NotUsed : 123654 **************************************** * DESCRIPTION *************************************** Header: xxx Date: 20010101 ReqDate:20150402 P.O. 1234

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

// 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; }
    }
}
公共类TestRegEx
{
private static readonly Regex KeyValFileRegex=new Regex(@“\b(?!:)[\w\.]++\s*[\s=:]\s*(?[^\n]*)(?=[^()\n]*[=:\(]),RegexOptions.IgnoreCase);
私有静态int Main(字符串[]args)
{
字符串inputStr=@”//这是一条注释
//未使用:123654
****************************************
*描述
***************************************
标题:xxx
日期:20010101
申请日期:20150402
邮政编码123456
数量10000
零件号:xx-yy-456
类型:J
产品:xxyy123456V0.01(散装)
客户编号:51
型号:
地点:60
UPC:123456
*
顾客:你好,沃尔克
*
***************************************
*资料
***************************************";
var stream=newmemoryStream(Encoding.UTF8.GetBytes(inputStr));
使用(var=新的流阅读器(流))
{
var data=新数据();
弦线;
而((line=r.ReadLine())!=null)
{
var match=KeyValFileRegex.match(行);
如果(!match.Success)继续;
var key=match.Groups[“key”].Value;
var value=match.Groups[“value”].value;
如果(!string.IsNullOrEmpty(value))value=value.Trim();
开关(钥匙)
{
案例“标题”:
数据头=值;
打破
案例“重新申请日期”:
data.RequestedDeliveryDate=值;
打破
案例“数量”:
数据数量=转换为32(值);
打破
案例“类型”:
数据类型=值;
打破
}
}
}
返回0;
}
私有类数据
{
公共字符串头{set;get;}
公共字符串RequestedDeliveryDate{set;get;}
公共字符串品牌{set;get;}
公共字符串Po{set;get;}
公共整数数量{set;get;}
公共字符串类型{set;get;}
}
}

任何帮助都将不胜感激。

您当前的正则表达式有缺陷,“Cust ID”字段以“Cust”作为键返回,其余部分作为值。原因是正则表达式的
[\s=:]
部分。它被配置为使用空格和冒号字符作为分隔符

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


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

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

因此,如果没有冒号,您将使用什么来确定不同的字段?您是否考虑过只编写代码来解析此字段?对于每一行,请检查要跳过的
/
*
或空行。其他所有内容都要查找要拆分的冒号,或者如果第一个空格上没有冒号拆分。如果没有空格,请跳过。您的答案不会小修改技巧:您使用的索引([1]&[2])不是捕获组,您应该使用([2]&[3]),并检查拆分的长度(大小>2).我只是按原样运行了您的代码,并且Dict上的所有键都是空字符串,我假设每次命中第一个匹配项都是空的。我会再次检查它。.我想我终于找到了。您可以逐行读取字符串,获取描述部分,然后使用正则表达式解析,并填充所需的数据对象字段。您可以添加更多字段支持rt以满足您的要求。