Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.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# 正则表达式捕获重复字段?_C#_Regex - Fatal编程技术网

C# 正则表达式捕获重复字段?

C# 正则表达式捕获重复字段?,c#,regex,C#,Regex,我试图用正则表达式解析一个缓冲区 以下是缓冲区的一个示例: DATA#ALPHAONE;BETATWO.CHARLIETHREE! 格式是:缓冲区总是以“DATA#”开头,作为文本头。 之后,它将有一个或多个文本字段,用分号、句号或感叹号分隔 到目前为止,我的正则表达式模式(C#)是: string singleFieldPattern = "(?'Field'.*?)(?'Separator'[;.!])"; string fullBufferPattern = "(?'Header'DAT

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

以下是缓冲区的一个示例:

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
BETATWO
(以及它们的分隔符
)。它只捕获最后一个字段(
CHARLIETHREE

如何获得所有匹配的
singleFieldPattern


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

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

例如:

[SYN] % SYSNAMScanner[ACK]; BAUDRATE57600[ACK]; CTRLMODEXON[ACK];
翻译:
系统名称(SYSNAM)为“Scanner”
波特率为57600
流量控制是XON

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

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

ALPHAONE
BETATWO
CHARLIETHREE

那么,您想获取所有遵循标题模式或单字段模式的值吗

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

这应该很好,但不确定您还有哪些正在解析的内容。

如果您不介意使用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();
编辑:要重现
调试
输出,请使用:

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

这一位LINQ将把regex中的字段和分隔符配对在一起:

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

你必须使用正则表达式吗?否则,string.Split()将得到您需要的。@hometoast:我的实际缓冲区要复杂得多,需要一个正则表达式。但出于提问的目的,我将其简化为这个最小的示例。除非这只是您降低问题复杂性的副作用,否则这是一种奇怪的数据格式。我不认为您可以更改源代码使其成为更普通的格式?不幸的是,我无法控制源数据。如果你想看一看真实的数据,我会马上编辑这个问题。@hometoos:很遗憾你删除了你的答案,因为“Captures”属性正是我需要的。如果你取消删除或重新发布,我会很高兴地投票并接受你的答案。涉及Linq的其他答案也很有效。组的
捕获
元素正是我所需要的。我以前只是忽略了它。多谢!
Header : DATA#
Field : ALPHAONE
Separator : ;
Field : BETATWO
Separator : .
Field : CHARLIETHREE
Separator : !
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 = ! }