我有一个缓冲区,我正试图用正则表达式解析。
以下是缓冲区的示例:
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)是“扫描仪”
波特率为57,600
流量控制是XON
答案 0 :(得分: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 : !
答案 1 :(得分: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 = ! }
答案 2 :(得分:1)
我在VB中尝试这个(因为这是我打开的),但考虑为群组迭代Capture:
For Each m As Capture In response.Match(example).Groups("Field").Captures
Debug.WriteLine(m.Value)
Next
给了我
ALPHAONE
BETATWO
CHARLIETHREE
答案 3 :(得分:1)
所以你想获得标题模式或单个字段模式之后的所有值吗?
"(?'Header'^DATA#)|(?'Field'.*?)(?'Separator'[;.!])"
应该做得很好,不知道你还有什么你正在解析的。