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

c#使用表达式解析字符串

我相信这个正则表达式将帮助您将字符串分解为相关组件:

([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资源。