使用正则表达式从此字符串获取字符串模式

使用正则表达式从此字符串获取字符串模式

问题描述:

我有一个字符串,如下所示在我的C#应用​​程序中。使用正则表达式从此字符串获取字符串模式

Multiply(Sum(3,5,4), Division(4,5,5), Subtract(7,8,9)) 

Sum()Division()Subtract()Multiple()内的不同的不同方法。

有没有什么办法像Sum(3,5,4),Division(4,5,5),Substract(7,8,9)Multiply()使用C#Regex方法分别得到每一个?

Sum,Division,SubstractMultiply是常数关键字。

+3

你打算窝他们进一步?说,乘以(乘(乘(1,2),乘(3,4)),乘(5,6))?还需要嵌套的 – dasblinkenlight 2012-01-09 14:00:30

+0

。那可能吗 ? – user904567 2012-01-09 14:28:58

+0

我的解决方案如下处理嵌套。因为需要嵌套,所以你不能用一个简单的Regex方法调用它,你必须使用for循环。这不应该是一个大问题。 – 2012-01-09 15:40:34

是的,如果你没有使用另一个方法调用时,将参数传递给你的方法。
(如Sum(2, Sum(3,2), 4)
在你可以使用这个模式的话:
^\w+\((.*)\)$再拿到1组(它是(*)组。)这是参数(Sum(3,5,4), Division(4,5,5), Subtract(7,8,9)),然后使用这个模式来getted组找到的所有参数:
\w+\(.*\)

如果您的乘方法可能有另一个嵌套方法,正则表达式不能帮助you.In这种情况下,你应该算括号,看看哪些wher关闭

如果嵌套任意深度,你应该这样做迭代地使用Regexp.Matches()Regexp.Replace()

复制整个字符串。使用([a-zA-Z]+\([0-9, ]*\))(,)?作为正则表达式。这将匹配所有最底层的函数调用 - 调用图的所有叶节点。

致电Regexp.Matches提取所有的匹配,请拨打Regexp.Replace摆脱他们所有的字符串副本。这将摆脱调用图的所有叶节点。再次呼叫Matches()Replace()以摆脱下一级调用,并继续重复,直到字符串副本为空。

+0

用'\ W启动+ \((\ d,?)+ \)',并在字符串通过,取代基于什么在你身边走过算出答案发现每场比赛,你会不停地重复这一点,直到最后一件事留在字符串中是答案。 – 2012-01-09 14:40:22

您无法使用RegExp进行任意嵌套 - 由于RegExp模型的限制,即使理论上也不可能是

你在这种情况下需要的是一个解析器。它不需要太多的工作来手动构建一个非常简单的recursive descent parser,但是一旦复杂性变得相当大,您应该切换到解析器生成器。我个人最喜欢的是ANTLR,但你有很多其他的选择。

C#应该能够通过正则表达式中的递归来实现平衡文本。唯一的问题是我认为它保留了整个外部比赛。为了进一步解析内部内容(在括号之间),需要递归函数调用,每次都选取令牌。

我同意@dasblinkenlight,但需要一个体面的解析器。正如他所说,复杂性可能迅速变得相当可观。

下面的正则表达式来自Perl,但构造对于.Net黑客应该是相同的。
正如你所看到的,正则表达式就像是在一般形式粘附于钛硅分子筛,但
只有逗号和数字是数学标记之间进行处理,使其余告吹。

但是,如果这是你所关心的唯一的事情,那么它应该工作。您会注意到即使您可以将它解析为数据结构(如下所示),但要以内部方式使用该结构,还需要在数据结构上进行另一个递归“解析”(尽管比较容易)。如果出于显示或统计目的,那么它不是问题。

扩展的正则表达式:

{ 
    (          #1 - Recursion group 1        
     \b(\w+)\s*        #2 - Math token 
     \(          # - Open parenth     
     (          #3 - Capture between parenth's 
      (?: (?> (?: (?!\b\w+\s*\(|\)) .)+)  # - Get all up to next math token or close parenth 
       | (?1)         # - OR, recurse group 1 
      )*          # - Optionally do many times 
     )          # - End capture 3 
     \)          # - Close parenth 
    )          # - End recursion group 1 
    \s*(\,?)        #4 - Capture optional comma ',' 

    |         # OR, 
             # (Here, it is only getting comma and digits, ignoring the rest. 
             # Comma's ',' are escaped to make them standout) 
    \s*          
    (?|         # - Start branch reset 
     (\d+)\s*(\,?)       #5,6 - Digits then optional comma ',' 
     | (?<=\,)()\s*(\,|\s*$)     #5,6 - Comma behind. No digit then, comma or end 
    )          # - End branch reset 
}xs; # Options: expanded, single-line 

这里是一个快速原型在Perl(更容易比C#):

use Data::Dumper; 


#// 
my $regex = qr{(\b(\w+)\s*\(((?:(?>(?:(?!\b\w+\s*\(|\)).)+)|(?1))*)\))\s*(\,?)|\s*(?|(\d+)\s*(\,?)|(?<=\,)()\s*(\,|\s*$))}s; 


#// 
my $sample = ', asdf Multiply(9, 4, 3, hello, _Sum(3,5,4,) , Division(4, Sum(3,5,4), 5), ,, Subtract(7,8,9))'; 

print_math_toks(0, $sample); 

my @array; 
store_math_toks(0, $sample, \@array); 
print Dumper(\@array); 


#// 
sub print_math_toks 
{ 
    my ($cnt, $segment) = @_; 
    while ($segment =~ /$regex/g) 
    { 
     if (defined $5) { 
     next if $cnt < 1; 
     print "\t"x($cnt+1), "$5$6\n"; 
     } 
     else { 
     ++$cnt; 
     print "\t"x$cnt, "$2(\n"; 
     my $post = $4; 

     $cnt = print_math_toks($cnt, $3); 

     print "\t"x$cnt, ")$post\n"; 
     --$cnt; 
     } 
    } 
    return $cnt; 
} 


sub store_math_toks 
{ 
    my ($cnt, $segment, $ary) = @_; 
    while ($segment =~ /$regex/g) 
    { 
     if (defined $5) { 
     next if $cnt < 1; 
     if (length $5) { 
      push (@$ary, $5); 
     } 
     else { 
      push (@$ary, ''); 
     } 
     } 
     else { 
     ++$cnt; 
     my %hash; 
     $hash{$2} = []; 
     push (@$ary, \%hash); 

     $cnt = store_math_toks($cnt, $3, $hash{$2}); 

     --$cnt; 
     } 
    } 
    return $cnt; 
} 

输出:

 Multiply(
       9, 
       4, 
       3, 
       _Sum(
         3, 
         5, 
         4, 

       ), 
       Division(
         4, 
         Sum(
           3, 
           5, 
           4 
         ), 
         5 
       ), 
       , 
       , 
       Subtract(
         7, 
         8, 
         9 
       ) 
     ) 
$VAR1 = [ 
      { 
      'Multiply' => [ 
          '9', 
          '4', 
          '3', 
          { 
           '_Sum' => [ 
              '3', 
              '5', 
              '4', 
              '' 
             ] 
          }, 
          { 
           'Division' => [ 
               '4', 
               { 
               'Sum' => [ 
                  '3', 
                  '5', 
                  '4' 
                 ] 
               }, 
               '5' 
              ] 
          }, 
          '', 
          '', 
          { 
           'Subtract' => [ 
               '7', 
               '8', 
               '9' 
              ] 
          } 
          ] 
      } 
     ];