c#使用表达式解析字符串
本文关键字:字符串 表达式 | 更新日期: 2023-09-27 17:57:38
我在Windows C#表单中有以下代码,用于解析文本框字符串。典型的字符串看起来像:
z5 100c x87.50。
另一个例子可能是:
m5 100c与z5 100c。
在这两个例子中,我都有各种重要的属性,"z5'"、"100"、"c"、"x"、"87.50"。从这个字符串中,我将其输入到各种函数中(这些函数不那么重要)。
我找到了各种示例,并有下面的代码,但当我运行代码时,它只会解析第一个找到的表达式,而不会遍历和显示所有找到的表达式。例如,"z5 100c x87.50"返回5和c.
字符串中的相关信息:m5 100c vs z5 100c。"m"这是一个月的符号。"5"是一年。"100"是一个价格。"c"是一个结构。"vs"是一个定价函数或所谓的差分函数。"z"是一个月的符号。"5"是一年。"100"是一个单独的价格。"c"是一个单独的结构。
有没有更好的方法可以读取整个字符串,然后解析和提取相关信息?
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.");
}
}
我相信这个正则表达式将帮助您将字符串分解为相关组件:
([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);
}
这会给你:
价格结构:
年月:z5
价格结构:100c
年月:
如果你想进一步分解它,你可以这样做(注意下面的+的用法相当于上面例子中的{1,}):
(?<price>[0-9.]+)(?<structure>[c]+)|(?<year>[zx]+)(?<month>[0-9.]+)
我用or运算符|将价格/结构和年/月分隔开,以说明在上下文重要的情况下,如何将组保持在一起,例如,如果首先加上价格,则c仅表示"结构"。我还将x添加到了year中,以说明如何轻松地将其他字符添加到一组可行的匹配字符中,正如PhatWrat在下面指出的那样。
新的正则表达式将产生:
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)
你可以在这个在线测试网站上试用:http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx
是的,我会看看Irony,一个解析器,它可以让你在几分钟内创建一个语法树(显然,你需要添加学习曲线!!)。
- http://irony.codeplex.com/
你会在网上找到好的样品。例如:
- http://www.codeproject.com/Articles/26975/Writing-Your-First-Domain-Specific-Language-Part
这里有另一个想法——您可以使用捕获组。我相信有一种更优雅的方法可以做到这一点,但它会像这样:
首先,设置你的捕获(我在这里只包含了3个——你需要添加你想要支持的任何其他内容)
Regex myRe = new Regex(@"m(?<month>'d+)|(?<price>'d+)c|z(?<compMonth>'d+)");
然后使用"匹配"
var myMatches = myRe.Matches(stringToSearch);
最后(对于那些比我更擅长regex的人来说,我认为这可能是可以重构的)查看您的匹配并寻找您的组:
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
顺便说一下,我建议将此备忘单和regexpal作为有用的RegEx资源。