有这样一组字符串例子~~~
            string str1 = @"
if '年终奖' <> '年终奖' :
  if 150 < 0 : 0
  elif 150<=500 and 150>0 : 150*0.05-0-1554
  elif 150<=2000 and 150>500 : 150*0.10-25-1554
  elif 150<=5000 and 150>2000 : 150*0.15-125-1554
  elif 150<=20000 and 150>5000 : 150*0.20-375-1554
  elif 150<=40000 and 150>20000 : 150*0.25-1375-1554
  else : -99999

elif '年终奖' == '年终奖' :
      if 150 < 0 :
            if (-9999+150)/12<=500 and (-9999+150)/12>0 : (-9999+150)/12*0.05-0
            elif (-9999+150)/12<=2000 and (-9999+150)/12>500 : (-9999+150)/12*0.10-25
            elif (-9999+150)/12<=5000 and (-9999+150)/12>2000 : (-9999+150)/12*0.15-125
            elif (-9999+150)/12<=20000 and (-9999+150)/12>5000 : (-9999+150)/12*0.20-375
            elif (-9999+150)/12<=40000 and (-9999+150)/12>20000 : (-9999+150)/12*0.25-1375
            else : -99999
      elif 150 > 0 :
        if -9999/12<=500 and -9999/12>0 : -9999/12*0.05-0
        elif -9999/12<=2000 and -9999/12>500 : -9999/12*0.10-25
        elif -9999/12<=5000 and -9999/12>2000 : -9999/12*0.15-125
        elif -9999/12<=20000 and -9999/12>5000 : -9999/12*0.20-375
        elif -9999/12<=40000 and -9999/12>20000 : -9999/12*0.25-1375
        else : -99999

else :   -99999
";
要点:
1.从前缩进的空格数可以看出是否同组的if else。
2.顶层的if else 肯定是非空格开头的。
3.非顶层的同级的不同组的空格数不一定相同,如例子。
4.表达式规则一般有一下几种:
第一种:
if <条件>  : <结果>   _回车
elif <条件>  : <结果>   _回车
else  : <结果>
这种情况一般<结果>是单个计算表达式,没有if else子逻辑运算表达式
第二种:
if <条件>  :    _回车
<结果>   _回车
elif <条件>  :   _回车
<结果>   _回车
else  : 
<结果>
这种<结果>一般是单个计算表达式或含有if else的子逻辑运算表达式
第三种:
混用的情况,如例子的顶层的if和最后的else。
5.存在只有if没有elif或else的情况。
6.<结果>内可能嵌套其他if else表达式,不过if else前肯定有缩进空格
7.if elif else肯定都是小写。需求很简单,想要通过正则表达式得到顶层的没有前空格的if elif else里的粗体<条件>部分和斜体<条件>的键值对数组,数组需要按表达式实际的if elif else顺序排好。
要考虑以上各种要点,以及4点所列的组合情况。先谢了!!!

解决方案 »

  1.   

    key1 = "#类型# <> '年终奖'" value1 =@"  if {应税额} < 0 : 0
      elif {应税额} <=500 and {应税额}>0 : {应税额}*0.05-0-{当月历史非年终奖非固定所得税}-{当月历史月工资所得税}
      elif {应税额} <=2000 and {应税额}>500 : {应税额}*0.10-25-{当月历史非年终奖非固定所得税}-{当月历史月工资所得税}
      elif {应税额} <=5000 and {应税额}>2000 : {应税额}*0.15-125-{当月历史非年终奖非固定所得税}-{当月历史月工资所得税}
      elif {应税额} <=20000 and {应税额}>5000 : {应税额}*0.20-375-{当月历史非年终奖非固定所得税}-{当月历史月工资所得税}
      elif {应税额} <=40000 and {应税额}>20000 : {应税额}*0.25-1375-{当月历史非年终奖非固定所得税}-{当月历史月工资所得税}
      else : -99999"
    key2 = "#类型# == '年终奖'" value2 =@"  if {应税额} < 0 :
        if (#奖金#+{应税额})/12 <=500 and (#奖金#+{应税额})/12>0 : (#奖金#+{应税额})/12*0.05-0
        elif (#奖金#+{应税额})/12 <=2000 and (#奖金#+{应税额})/12>500 : (#奖金#+{应税额})/12*0.10-25
        elif (#奖金#+{应税额})/12 <=5000 and (#奖金#+{应税额})/12>2000 : (#奖金#+{应税额})/12*0.15-125
        elif (#奖金#+{应税额})/12 <=20000 and (#奖金#+{应税额})/12>5000 : (#奖金#+{应税额})/12*0.20-375
        elif (#奖金#+{应税额})/12 <=40000 and (#奖金#+{应税额})/12>20000 : (#奖金#+{应税额})/12*0.25-1375
        else : -99999
      elif {应税额} > 0 :
        if #奖金#/12 <=500 and #奖金#/12>0 : #奖金#/12*0.05-0
        elif #奖金#/12 <=2000 and #奖金#/12>500 : #奖金#/12*0.10-25
        elif #奖金#/12 <=5000 and #奖金#/12>2000 : #奖金#/12*0.15-125
        elif #奖金#/12 <=20000 and #奖金#/12>5000 : #奖金#/12*0.20-375
        elif #奖金#/12 <=40000 and #奖金#/12>20000 : #奖金#/12*0.25-1375
        else : -99999"
    key3 = "" value3 =@"  -99999"
    上面最后一个为空,是因为else里没有条件表达式。
      

  2.   

    试试这个:
    @"(?msi)^(\s*)if\b(?<key1>.*?):(?<value1>.*?)(^\1elif\b(?<key2>.*?):(?<value2>.*?))*(^\1else\b(?<key3>.*?):?<value3>.*?))*"
      

  3.   

    @"(?msi)^(\s*)if\b(?<key1>.*?):(?<value1>.*?)(^\1elif\b(?<key2>.*?):(?<value2>.*?))*(^\1else\b(?<key3>.*?):(?<value3>.*?))*"
      

  4.   

    using System;
    using System.Text.RegularExpressions;   class Test
    {
      static string str1 = @"
    if '年终奖' <> '年终奖' : 
      if 150 < 0 : 0 
      elif 150 <=500 and 150>0 : 150*0.05-0-1554 
      elif 150 <=2000 and 150>500 : 150*0.10-25-1554 
      elif 150 <=5000 and 150>2000 : 150*0.15-125-1554 
      elif 150 <=20000 and 150>5000 : 150*0.20-375-1554 
      elif 150 <=40000 and 150>20000 : 150*0.25-1375-1554 
      else : -99999 
    elif '年终奖' == '年终奖' : 
          if 150 < 0 : 
                if (-9999+150)/12 <=500 and (-9999+150)/12>0 : (-9999+150)/12*0.05-0 
                elif (-9999+150)/12 <=2000 and (-9999+150)/12>500 : (-9999+150)/12*0.10-25 
                elif (-9999+150)/12 <=5000 and (-9999+150)/12>2000 : (-9999+150)/12*0.15-125 
                elif (-9999+150)/12 <=20000 and (-9999+150)/12>5000 : (-9999+150)/12*0.20-375 
                elif (-9999+150)/12 <=40000 and (-9999+150)/12>20000 : (-9999+150)/12*0.25-1375 
                else : -99999 
          elif 150 > 0 : 
            if -9999/12 <=500 and -9999/12>0 : -9999/12*0.05-0 
            elif -9999/12 <=2000 and -9999/12>500 : -9999/12*0.10-25 
            elif -9999/12 <=5000 and -9999/12>2000 : -9999/12*0.15-125 
            elif -9999/12 <=20000 and -9999/12>5000 : -9999/12*0.20-375 
            elif -9999/12 <=40000 and -9999/12>20000 : -9999/12*0.25-1375 
            else : -99999 
    else :   -99999 
    ";  static void Main()
      {
        string pattern = @"(?msix)
    ^(\s*)if\b(?<key1>.*?):(?<value1>.*?)
    (^\1elif\b(?<key2>.*?):(?<value2>.*?))*
    (^\1else\b(?<key3>.*?):(?<value3>.*))
    ";
        MatchCollection mc = Regex.Matches(str1, pattern);
        foreach (Match m in mc)
        {
          // 匹配到的第一个 if 的 key1 及 value1
          string key1   = m.Groups["key1"  ].Value.Trim();
          string value1 = m.Groups["value1"].Value.Trim();
          Console.WriteLine("Key1   = [{0}]", key1  );
          Console.WriteLine("Value1 = [{0}]", value1);
          
          // 匹配到的 elif 的 key2 及 value2 (可能有多个捕获组)
          int i = 0;
          foreach (Capture c in m.Groups["key2"].Captures)
          {
            string key2   = c.Value.Trim();
            string value2 = m.Groups["value2"].Captures[i++].Value.Trim();
            Console.WriteLine("Key2   = [{0}]", key2  );
            Console.WriteLine("Value2 = [{0}]", value2);
          }      // 匹配到的 else 的 key3 及 value3
          string key3   = m.Groups["key3"  ].Value.Trim();
          string value3 = m.Groups["value3"].Value.Trim();
          Console.WriteLine("Key3   = [{0}]", key3  );
          Console.WriteLine("Value3 = [{0}]", value3);
        }
      }
    }
      

  5.   

        string pattern = @"(?msix)
    ^(\s*)if\b(?<key1>.*?):(?<value1>.*?)
    (^\1elif\b(?<key2>.*?):(?<value2>.*?))*
    (^\1else\b(?<key3>.*?):(?<value3>.*))
    ";/*
    这个表达式用 ^(\s*)if 记录了 if 前面的空格,
    然后用 ^\1elif 反向引用 \1 指明必须匹配和前面的 if 同样多的前导空格,行末的 * 表明可以有0个或多个 elif,
    最后, ^\1else 反向引用 \1 指明必须匹配和前面的 if 同样多的前导空格,但有个缺点是 else 是必须的。
    */
      

  6.   

    满足要求,谢谢了,不过有个小问题,能将结果的第一个if前面的空格保留么?if 150 < 0 : 0//这个想要和下面一行的elif前一样有个空格,就是该行字符串原来的样貌
     elif 150<=500 and 150>0 : 150*0.05-0-1554
     elif 150<=2000 and 150>500 : 150*0.10-25-1554
     elif 150<=5000 and 150>2000 : 150*0.15-125-1554
     elif 150<=20000 and 150>5000 : 150*0.20-375-1554
     elif 150<=40000 and 150>20000 : 150*0.25-1375-1554
     else : -99999还有,下面的这个结果不正确。            string str1 = @"
    if 150 < 0 :
          if (-9999+150)/12<=500 and (-9999+150)/12>0 : (-9999+150)/12*0.05-0
          elif (-9999+150)/12<=2000 and (-9999+150)/12>500 : (-9999+150)/12*0.10-25
          elif (-9999+150)/12<=5000 and (-9999+150)/12>2000 : (-9999+150)/12*0.15-125
          elif (-9999+150)/12<=20000 and (-9999+150)/12>5000 : (-9999+150)/12*0.20-375
          elif (-9999+150)/12<=40000 and (-9999+150)/12>20000 : (-9999+150)/12*0.25-1375
          else : -99999
    elif 150 > 0 :
      if -9999/12<=500 and -9999/12>0 : -9999/12*0.05-0
      elif -9999/12<=2000 and -9999/12>500 : -9999/12*0.10-25
      elif -9999/12<=5000 and -9999/12>2000 : -9999/12*0.15-125
      elif -9999/12<=20000 and -9999/12>5000 : -9999/12*0.20-375
      elif -9999/12<=40000 and -9999/12>20000 : -9999/12*0.25-1375
      else : -99999
    ";
      

  7.   

    using System.Text.RegularExpressions;
    using System;
    class Validation
    {
      public static void Main()
      {
        String strToTest;
        Validation objValidate=new Validation();    Console.Write("Enter a String to Test for Alphabets:");
        strToTest=Console.ReadLine();
        if(objValidate.IsAlpha(strToTest))
        {
          Console.WriteLine("{0} is Valid Alpha String",strToTest);
        }
        else
        {
          Console.WriteLine("{0} is not a Valid Alpha String",strToTest);
        }
      }
    public bool IsNaturalNumber(String strNumber)
      {
        Regex objNotNaturalPattern=new Regex("[^0-9]");
        Regex objNaturalPattern=new Regex("0*[1-9][0-9]*");    return  !objNotNaturalPattern.IsMatch(strNumber) &&
                objNaturalPattern.IsMatch(strNumber);
      }
    public bool IsWholeNumber(String strNumber)
        {
          Regex objNotWholePattern=new Regex("[^0-9]");      return !objNotWholePattern.IsMatch(strNumber);
        }
    public bool IsInteger(String strNumber)
        {
          Regex objNotIntPattern=new Regex("[^0-9-]");
          Regex objIntPattern=new Regex("^-[0-9]+$|^[0-9]+$");      return  !objNotIntPattern.IsMatch(strNumber) &&
                  objIntPattern.IsMatch(strNumber);
        }
    public bool IsPositiveNumber(String strNumber)
      {
        Regex objNotPositivePattern=new Regex("[^0-9.]");
        Regex objPositivePattern=new Regex("^[.][0-9]+$|[0-9]*[.]*[0-9]+$");
        Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*");    return !objNotPositivePattern.IsMatch(strNumber) &&
               objPositivePattern.IsMatch(strNumber)  &&
               !objTwoDotPattern.IsMatch(strNumber);
      }
    public bool IsNumber(String strNumber)
      {
        Regex objNotNumberPattern=new Regex("[^0-9.-]");
        Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*");
        Regex objTwoMinusPattern=new Regex("[0-9]*[-][0-9]*[-][0-9]*");
        String strValidRealPattern="^([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$";
        String strValidIntegerPattern="^([-]|[0-9])[0-9]*$";
        Regex objNumberPattern =new Regex("(" + strValidRealPattern +")|(" + strValidIntegerPattern + ")");    return !objNotNumberPattern.IsMatch(strNumber) &&
               !objTwoDotPattern.IsMatch(strNumber) &&
               !objTwoMinusPattern.IsMatch(strNumber) &&
               objNumberPattern.IsMatch(strNumber);
      }
    public bool IsAlpha(String strToCheck)
      {
        Regex objAlphaPattern=new Regex("[^a-zA-Z]");    return !objAlphaPattern.IsMatch(strToCheck);
      }  // Function to Check for AlphaNumeric.  public bool IsAlphaNumeric(String strToCheck)
      {
        Regex objAlphaNumericPattern=new Regex("[^a-zA-Z0-9]");    return !objAlphaNumericPattern.IsMatch(strToCheck);   
      }
    }
    给一个我的“正则表达式”的例子,希望对你有所帮助。仅供参考!
      

  8.   


    // 改成这样就能正确处理没有 “最后的 else ” 的情况了:
        string pattern = @"(?msix)
    ^(\s*)if\b(?<key1>.*?):(?<value1>.*?)    # 匹配 if 并记录前导空格
    (^\1elif\b(?<key2>.*?):(?<value2>.*?))*  # 匹配对应的 elif ,0个或多个
    (^\1else\b(?<key3>.*?):(?<value3>.*?))?  # 匹配对应的 else ,0个或1个
    \Z                                       # 匹配整个字符串末尾
    ";
      

  9.   


    可以,只要把程序中的所有的 .Trim() 去掉就可以了:    MatchCollection mc = Regex.Matches(str1, pattern);
        foreach (Match m in mc)
        {
          // 匹配到的第一个 if 的 key1 及 value1
          string key1   = m.Groups["key1"  ].Value;
          string value1 = m.Groups["value1"].Value;
          Console.WriteLine("Key1   = [{0}]", key1  );
          Console.WriteLine("Value1 = [{0}]", value1);
          
          // 匹配到的 elif 的 key2 及 value2 (可能有多个捕获组)
          int i = 0;
          foreach (Capture c in m.Groups["key2"].Captures)
          {
            string key2   = c.Value;
            string value2 = m.Groups["value2"].Captures[i++].Value;
            Console.WriteLine("Key2   = [{0}]", key2  );
            Console.WriteLine("Value2 = [{0}]", value2);
          }      // 匹配到的 else 的 key3 及 value3
          string key3   = m.Groups["key3"  ].Value;
          string value3 = m.Groups["value3"].Value;
          Console.WriteLine("Key3   = [{0}]", key3  );
          Console.WriteLine("Value3 = [{0}]", value3);不过,有可能会有多余的回车(没关系,不会造成障碍)。
      

  10.   

    还在测试中,目前比较理想,不过在没有else的时候,多匹配了一个键和值都为空的对,看看能否完善一小下。
      

  11.   

    http://msdn.microsoft.com/zh-cn/library/yd1hzczs.aspx.NET Framework 开发人员指南
    正则表达式选项可以使用影响匹配行为的选项修改正则表达式模式。可以通过下列两种基本方法之一设置正则表达式选项:可以在 Regex (pattern, options) 构造函数中的 options 参数中指定,其中 options 是 RegexOptions 枚举值的按位“或”组合;也可以使用内联 (?imnsx-imnsx:) 分组构造或 (?imnsx-imnsx) 其他构造在正则表达式模式内设置它们。在内联选项构造中,一个选项或一组选项前面的减号 (-) 用于关闭这些选项。例如,内联构造 (?ix-ms) 将打开 IgnoreCase 和 IgnorePatternWhiteSpace 选项而关闭 Multiline 和 Singleline 选项。默认情况下,关闭所有正则表达式选项。下表列出了 RegexOptions 枚举的成员以及等效的内联选项字符。请注意,选项 RightToLeft 和 Compiled 只适用于表达式整体而不允许内联。(它们只能在 Regex 构造函数的 options 参数中指定。) 选项 None 和 ECMAScript 不允许内联。RegexOption 成员
     内联字符
     说明
     
    None
     N/A
     指定不设置任何选项。
     
    IgnoreCase
     i
     指定不区分大小写的匹配。
     
    Multiline
     m
     指定多行模式。更改 ^ 和 $ 的含义,以使它们分别与任何行的开头和结尾匹配,而不只是与整个字符串的开头和结尾匹配。
     
    ExplicitCapture
     n
     指定唯一有效的捕获是显式命名或编号的 (?<name>…) 形式的组。这允许圆括号充当非捕获组,从而避免了由 (?:…) 导致的语法上的笨拙。
     
    Compiled
     N/A
     指定正则表达式将被编译为程序集。生成该正则表达式的 Microsoft 中间语言 (MSIL) 代码;以较长的启动时间为代价,得到更快的执行速度。
     
    Singleline
     s
     指定单行模式。更改句点字符 (.) 的含义,以使它与每个字符(而不是除 \n 之外的所有字符)匹配。
     
    IgnorePatternWhitespace
     x
     指定从模式中排除非转义空白并启用数字符号 (#) 后面的注释。(有关转义空白字符的列表,请参见字符转义。) 请注意,空白永远不会从字符类中消除。
     
    RightToLeft
     N/A
     指定搜索是从右向左而不是从左向右进行的。具有此选项的正则表达式将移动到起始位置的左边而不是右边。(因此,起始位置应指定为字符串的结尾而不是开头。) 为了避免构造具有无限循环的正则表达式的可能性,此选项不能在中流指定。但是,(?<) 回顾后发构造提供了可用作子表达式的类似替代物。RightToLeft 只更改搜索方向。它不会反转所搜索的子字符串。预测先行和回顾后发断言不改变:预测先行向右搜索;回顾后发向左搜索。
     
    ECMAScript
     N/A
     指定已为表达式启用了符合 ECMAScript 的行为。此选项仅可与 IgnoreCase 和 Multiline 标志一起使用。将 ECMAScript 同任何其他标志一起使用将导致异常。
     
    CultureInvariant
     N/A
     指定忽略语言中的区域性差异。有关更多信息,请参见在 RegularExpressions 命名空间中执行不区分区域性的操作。
     
      

  12.   

    在最后一小段前面加上是否实际捕获的判断 if (m.Groups["key3"].Success) 就可以了:      // 匹配到的 else 的 key3 及 value3
          if (m.Groups["key3"].Success)
          {
            string key3   = m.Groups["key3"  ].Value.Trim();
            string value3 = m.Groups["value3"].Value;
            Console.WriteLine("Key3   = [{0}]", key3  );
            Console.WriteLine("Value3 = [{0}]", value3);
          }