c#使用表达式解析字符串
我有以下Windows C#格式的代码,用于解析文本框字符串。典型的字符串如下所示: z5 100c x87.50 另一个例子可能是: m5 100c与z5 100c 在这两个例子中,我都有各种重要的属性,“z5”、“100”、“c”、“x”、“87.50”。从这个字符串中,我将其输入到各种函数中(这些函数不太重要) 我找到了各种示例,并且有下面的代码,但是当我运行代码时,它将只解析第一个找到的表达式,而不会遍历并显示所有找到的表达式 字符串中的相关信息:m5 100c vs z5 100c。“m”这是一个月符号。“5”是一年。“100”是一个价格。“c”是一个结构。“vs”是一个定价函数或所谓的差异函数。“z”是一个月符号。“5”是一年。“100”是一个单独的价格。“c”是一个单独的结构 是否有更好的方法读取整个字符串,然后解析和提取相关信息c#使用表达式解析字符串,c#,regex,expression,C#,Regex,Expression,我有以下Windows C#格式的代码,用于解析文本框字符串。典型的字符串如下所示: z5 100c x87.50 另一个例子可能是: m5 100c与z5 100c 在这两个例子中,我都有各种重要的属性,“z5”、“100”、“c”、“x”、“87.50”。从这个字符串中,我将其输入到各种函数中(这些函数不太重要) 我找到了各种示例,并且有下面的代码,但是当我运行代码时,它将只解析第一个找到的表达式,而不会遍历并显示所有找到的表达式 字符串中的相关信息:m5 100c vs z5 100c。“
private void toolStripButton2_Click(object sender, EventArgs e)
{
string contract = toolStripTextBox1.ToString();
string contractConvert = contract.ToLower();
Regex re = new Regex("c$\\.?|p$\\.?|s$\\.?|f$\\.?|cs\\.?|ps\\.?|vs\\.?|x\\.?");
Regex rePrice = new Regex("[0-9]{1,4}(\\.[0-9]{1,2})?");
Match m = re.Match(contractConvert.ToString());
Match mPrice = rePrice.Match(contract.ToString());
if (m.Success)
{
MessageBox.Show(string.Format("Structure: " + m.Value));
}
else
{
MessageBox.Show("Structure incorrect!");
}
if (mPrice.Success)
{
MessageBox.Show(string.Format("Strike: " + mPrice.Value));
}
else
{
MessageBox.Show("Structure incorrect! Requires a strike.");
}
}
是的,我想看看Irony,它是一个解析器,可以让你在几分钟内创建一个语法树(显然,你需要添加学习曲线!!)
([A-Za-z]{1,}[0-9.]*|[0-9.]{1,}[A-Za-z]*)
只需像这样使用匹配集合:
string pattern = "([A-Za-z]{1,}[0-9.]*|[0-9.]{1,}[A-Za-z]*)";
string input = "z5 100c x87.50.";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.WriteLine(match.Groups[1].Value);
}
将给你:
z5
100c
x87.50.
然后你可以根据需要进一步分析
您甚至可以使用命名的匹配组一次完成所有操作,以使您的生活更轻松……例如:
string pattern = "(?<price_structure>[0-9.]{1,}[c]{1,})|(?<year_month>[z]{1,}[0-9]{1,})";
string input = "z5 100c x87.50.";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.WriteLine("price-structure: " + match.Groups["price_structure"].Value);
Console.WriteLine("year-month: " + match.Groups["year_month"].Value);
}
您可以在以下在线测试网站上试用:
这里还有一个想法——你可以使用捕获组。我相信有一种更优雅的方法,但它会是这样的:
首先,设置您的捕获(我在这里只包括3个--您需要添加任何您想要支持的内容)
最后(对于那些比我更擅长正则表达式的人来说,我认为这可能是重构的)检查您的匹配并寻找您的组:
foreach (var v in myMatches)
{
Match myMatch = v as Match;
if (myMatch == null)
continue;
if(!string.IsNullOrEmpty(myMatch.Groups["month"].Value))
MessageBox.Show("Month = " + myMatch.Groups["month"].Value);
if (!string.IsNullOrEmpty(myMatch.Groups["price"].Value))
MessageBox.Show("Price = " + myMatch.Groups["price"].Value);
if (!string.IsNullOrEmpty(myMatch.Groups["compMonth"].Value))
MessageBox.Show("Other Month = " + myMatch.Groups["compMonth"].Value);
}
对于输入“m5 100c vs z5 100c”,您的输出将是:
月=5价格=100
其他月份=5
价格=100
顺便说一下,我建议将和作为有用的正则表达式资源。如果您不打算提供example@Martin在这里提供一个反讽的例子是没有意义的。“你知道更好的方法吗?”=>“是的,Irony.NET“。如果OP对另一个解决方案感兴趣,一个指向该项目的链接加上一篇CodeProject文章就足够了。我真的很困惑关于RegEx和需要循环的问题是如何导致关于使用反讽的答案的。不是说这是错的,而是想知道我错过了什么。@Matías Fidemraizer-我会看看你给出的例子。看来树的概念是一个很好的解决方案,但是有一个学习曲线。@TyCobb你没有打开你的思路,是的!;)这不是关于regexp的问题。这是一个关于寻找更好的方法来解析这些字符串的问题!!我发现最好使用Irony(或其他解析器),而不是尝试使用regexp解析字符串,因为您将在更少的代码行中获得更可靠的结果,并且更易于扩展。为什么不呢?我不确定你是否需要一个框架(根据答案,这意味着讽刺),但这个问题非常不清楚,我也不确定我是否理解它。请您澄清一下,例如,如果给定“z5 100c x87.50”的示例输入,您希望隔离哪些组件。似乎您可能希望使用一个正则表达式通过匹配组将其分解为更小的组件,然后您可能还需要另一个正则表达式将这些组件进一步分解为各自的部分。如果您能提供清晰的信息,我可能会提供进一步的指导!添加了有关信息的信息。来自字符串示例:m5 100c与z5 100c。这是一个月的符号。“5”是一年。“100”是一个价格。“c”是一个结构。“vs”是一个定价函数或所谓的差异函数。“z”是一个月的符号。“5”是一年。“100”是一个单独的价格。“c”是一个单独的结构。请告诉我我的回答是否有帮助和/或我是否可以进一步澄清。如果您发现一个可接受的答案,请务必接受答案。我注意到的一个问题是正则表达式是一种静态格式。例如m(?\d+)。那只是“m”。但是,如果有人引用其他月份类型,这将不起作用。正确-这确实会做出一些假设,这些假设可能适用于您的项目,也可能不适用于您的项目。请注意,我为您比较的月份提供了
z(?\d+)
(无论如何,据我所知)。如果您想将它们组合在一起,您可以执行类似于[mz](?\d+)
的操作。您还可以根据需要添加单词边界(\w
)、look aheads((?=m)
)和/或大量其他限制。显然,为了让这一切顺利进行,您需要知道您正在寻找什么,并对搜索空间有一个非常好的了解。请进行一次升级,因为我认为您在提交一份编辑之前提交了匹配组部分,其中包含了如何使用匹配组的信息,以及提醒我我可以使用cleaner+语法:)
z5 has 4 groups:
(price)
(structure)
z (year)
5 (month)
100c has 4 groups:
100 (price)
c (structure)
(year)
(month)
x87.50. has 4 groups:
(price)
(structure)
x (year)
87.50. (month)
Regex myRe = new Regex(@"m(?<month>\d+)|(?<price>\d+)c|z(?<compMonth>\d+)");
var myMatches = myRe.Matches(stringToSearch);
foreach (var v in myMatches)
{
Match myMatch = v as Match;
if (myMatch == null)
continue;
if(!string.IsNullOrEmpty(myMatch.Groups["month"].Value))
MessageBox.Show("Month = " + myMatch.Groups["month"].Value);
if (!string.IsNullOrEmpty(myMatch.Groups["price"].Value))
MessageBox.Show("Price = " + myMatch.Groups["price"].Value);
if (!string.IsNullOrEmpty(myMatch.Groups["compMonth"].Value))
MessageBox.Show("Other Month = " + myMatch.Groups["compMonth"].Value);
}