2012-01-09 129 views
2

我有一個字符串,如下所示在我的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

回答

0

是的,如果你沒有使用另一個方法調用時,將參數傳遞給你的方法。
(如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關閉

1

如果嵌套任意深度,你應該這樣做迭代地使用Regexp.Matches()Regexp.Replace()

複製整個字符串。使用([a-zA-Z]+\([0-9, ]*\))(,)?作爲正則表達式。這將匹配所有最底層的函數調用 - 調用圖的所有葉節點。

致電Regexp.Matches提取所有的匹配,請撥打Regexp.Replace擺脫他們所有的字符串副本。這將擺脫調用圖的所有葉節點。再次呼叫Matches()Replace()以擺脫下一級調用,並繼續重複,直到字符串副本爲空。

+0

用'\ W啓動+ \((\ d,?)+ \)',並在字符串通過,取代基於什麼在你身邊走過算出答案發現每場比賽,你會不停地重複這一點,直到最後一件事留在字符串中是答案。 – 2012-01-09 14:40:22

1

您無法使用RegExp進行任意嵌套 - 由於RegExp模型的限制,即使理論上也不可能是

你在這種情況下需要的是一個解析器。它不需要太多的工作來手動構建一個非常簡單的recursive descent parser,但是一旦複雜性變得相當大,您應該切換到解析器生成器。我個人最喜歡的是ANTLR,但你有很多其他的選擇。

0

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' 
              ] 
          } 
          ] 
      } 
     ];