4

我有一个试图用正则表达式解析的缓冲区。

这是缓冲区的示例:

DATA#ALPHAONE;BETATWO.CHARLIETHREE!

格式为:缓冲区始终以“DATA#”开头,作为文字标头。之后,它将有一个或多个文本字段,由分号、句点或感叹号分隔。

到目前为止,我的正则表达式模式(在 C# 中)是:

string singleFieldPattern = "(?'Field'.*?)(?'Separator'[;.!])";
string fullBufferPattern = "(?'Header'DATA#)(" + singleFieldPattern + ")+";

当我尝试转储匹配的数据时,问题就来了:

Regex response = new Regex(fullBufferPattern);
string example = "DATA#ALPHAONE;BETATWO.CHARLIETHREE!";

Debug.WriteLine("RegEx Matches?: {0}", response.IsMatch(example));  
foreach (Match m in response.Matches(example))
{
    foreach(string s in new string[]{"Header", "Field", "Separator"}) 
    {
        Debug.WriteLine("{0} : {1}", s, m.Groups[s]);
    }
}

唯一的输出是:

RegEx Matches?: True
Header : DATA#
Field : CHARLIETHREE
Separator : !

我打算输出是:

RegEx Matches?: True
Header : DATA#
Field : ALPHAONE
Separator : ;
Field : BETATWO
Separator : .
Field : CHARLIETHREE
Separator : !

我的表达没有像我想要的那样得到早期的字段ALPHAONE和(以及它们的andBETATWO的分隔符)。它只捕获了最后一个字段 ( )。;.CHARLIETHREE

我怎样才能得到所有匹配的部分singleFieldPattern


出于提问的目的,我已经简化了上面的数据格式,但是由于有些人想要真实数据,所以这里更接近实际数据:

(注意:[ ]中的值是不可打印的单字节,空格仅是为了清楚起见。)

例子:

[SYN] % SYSNAMScanner[ACK]; BAUDRATE57600[ACK]; CTRLMODEXON[ACK];

翻译:
系统名称 (SYSNAM) 是“扫描仪”
波特率是 57,600
流量控制是 XON

4

4 回答 4

3

这部分 LINQ 会将您的正则表达式中的字段和分隔符配对:

var ms = response.Matches(example);
foreach (Match m in ms)
{
    string header = m.Groups["Header"].Value;
    Debug.WriteLine("Header : " + header);
    var pairs = m.Groups["Field"].Captures.Cast<Capture>().Zip(
                    m.Groups["Separator"].Captures.Cast<Capture>(),
                    (f, s) => new { Field = f.Value, Separator = s.Value });
    foreach (var pair in pairs)
    {
        Debug.WriteLine(pair.ToString());
    }
}

这输出:

Header : DATA#
{ Field = ALPHAONE, Separator = ; }
{ Field = BETATWO, Separator = . }
{ Field = CHARLIETHREE, Separator = ! }
于 2013-07-12T17:37:28.360 回答
3

如果你不介意一点 LINQ,你可以这样做:

string data = "DATA#ALPHAONE;BETATWO.CHARLIETHREE!";
var fullBufferPattern = @"(?<header>DATA#)(?<fields>.+)[;.!]";
var fieldPattern = @"(?<field>[^;.!]+)[;.!]?";

var fields = Regex.Matches(data, fullBufferPattern)
                    .OfType<Match>()
                    .SelectMany(
                        m =>
                        Regex.Matches(m.Groups["fields"].Value, fieldPattern)
                             .OfType<Match>())
                    .Select(m => m.Groups["field"].Value).ToArray();

该变量fields将具有:

ALPHAONE    
BETATWO
CHARLIETHREE

编辑:要重现您Debug的输出,请使用:

string data = "DATA#ALPHAONE;BETATWO.CHARLIETHREE!";
var fullBufferPattern = @"(?<header>DATA#)(?<fields>([^;.!]+[;.!])+)";
var fieldPattern = @"(?<field>[^;.!]+)(?<separator>[;.!])";

var groups = Regex.Matches(data, fullBufferPattern)
                  .OfType<Match>()
                  .Select(
                      m =>
                      new
                      {
                          Header = m.Groups["header"],
                          Fields = Regex.Matches(m.Groups["fields"].Value, fieldPattern)
                                        .OfType<Match>()
                                        .Select(f => new
                                            {
                                                Field = f.Groups["field"],
                                                Separator = f.Groups["separator"]
                                            })
                      });

foreach (var element in groups)
{
    Debug.WriteLine("Header : {0}", element.Header);
    foreach (var field in element.Fields)
    {
        Debug.WriteLine("Field : {0}", field.Field);
        Debug.WriteLine("Separator : {0}", field.Separator);
    }
}

输出是:

Header : DATA#
Field : ALPHAONE
Separator : ;
Field : BETATWO
Separator : .
Field : CHARLIETHREE
Separator : !
于 2013-07-12T17:25:41.730 回答
1

所以你想获得所有遵循标题模式或单个字段模式的值?

"(?'Header'^DATA#)|(?'Field'.*?)(?'Separator'[;.!])"

那应该没问题,但不确定你还有什么要解析的。

于 2013-07-12T17:22:02.910 回答
1

我在 VB 中尝试这个(因为这是我打开的),但考虑为组迭代 Capture:

  For Each m As Capture In response.Match(example).Groups("Field").Captures
     Debug.WriteLine(m.Value)
  Next

给我

ALPHAONE
BETATWO
CHARLIETHREE
于 2013-07-12T17:18:52.867 回答