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 = ! }