正则表达式问题

时间:2011-05-23 15:24:09

标签: regex

获得所有匹配的正则表达式是什么:

IF(.....);

我需要获取上一个字符串的开头和结尾:内容也可以是(),然后可以是其他(... IF (...) ....) 我只需要 IF 内的内容。 有什么想法吗?

那是因为,我需要得到一个Excel公式(如果条件)并将其转换为另一种语言(java脚本)。

修改
我试过了

       `/IF\s*(\(\s*.+?\s*\))/i or /IF(\(.+?\))/`

这不起作用,因为只有在)

内没有('IF(...)'时才匹配

5 个答案:

答案 0 :(得分:3)

我怀疑你有一个不适合正则表达式匹配的问题。你想做无限计数(所以你可以匹配开括号和右括号),这不仅仅是正则表达式可以处理的。但是,手动滚动解析器以进行所需的匹配应该不会很难。

基本上(伪代码):

Find "IF"
Ensure next character is "("
Initialise counter parendepth to 1
While parendepth > 0:
  place next character in ch
  if ch == "(":
    parendepth += 1
  if ch == ")":
    parendepth -= 1

添加少量“记住开始”和“记住结束”,你应该全部设定。

答案 1 :(得分:1)

这是Perl中的一种方法。任何允许递归的正则表达式 应具备这种能力。
在这个例子中,正确的括号被注释的事实 (见输出)和平衡,意味着它可以存储数据
以结构化的方式 这绝不会验证任何东西,它只是一个快速的解决方案。

use strict;
use warnings;

##
 $/ = undef;
 my $str = <DATA>;
 my ($lvl, $keyword) = ( 0, '(?:IF|ELSIF)' ); # One or more keywords
                                              # (using 2 in this example)    
 my $kwrx = qr/
   (\b $keyword \s*)        #1  - keword capture group
   (                        #2  - recursion group
     \(      # literal '('
        (                   #3  - content capture group
          (?:
              (?>  [^()]+ )    # any non parenth char
            | (?2)             # or, recurse group 2
          )*
        )
     \)      # literal ')'
   )
 | ( (?:(?!\b $keyword \s*).)+ )   #4
 | ($keyword)                      #5
 /sx;

##
 print "\n$str\n- - -\n";
 findKeywords ( $str );
 exit 0;

##
sub findKeywords
{
  my ($str) = @_;
  while ($str =~ /$kwrx/g)
  {
    # Process keyword(s), recurse its contents

      if (defined $2) {
        print "${1}[";
        $lvl++;
        findKeywords ( $3 );
      }
    # Process non-keyword text

      elsif (defined $4) {
        print "$4";
      }
      elsif (defined $5) {
         print "$5";
      }
  }
  if ($lvl > 0) {
      print ']';
      $lvl--;
  }
}

__DATA__

  IF( some junk IF (inner meter(s)) )
  THEN {
    IF ( its in
         here
         ( IF (a=5)
           ELSIF
           ( b=5
             and IF( a=4 or
                     IF(its Monday) and there are
                     IF( ('lots') IF( ('of') IF( ('these') ) ) )
                   )
           )
         )
         then its ok
       ) 
    ELSIF ( or here() )
    ELSE (or nothing)
  } 

输出:

  IF( some junk IF (inner meter(s)) )
  THEN {
    IF ( its in
         here
         ( IF (a=5)
           ELSIF
           ( b=5
             and IF( a=4 or
                     IF(its Monday) and there are
                     IF( ('lots') IF( ('of') IF( ('these') ) ) )
                   )
           )
         )
         then its ok
       )
    ELSIF ( or here() )
    ELSE (or nothing)
  }

- - -

  IF[ some junk IF [inner meter(s)] ]
  THEN {
    IF [ its in
         here
         ( IF [a=5]
           ELSIF
           [ b=5
             and IF[ a=4 or
                     IF[its Monday] and there are
                     IF[ ('lots') IF[ ('of') IF[ ('these') ] ] ]
                   ]
           ]
         )
         then its ok
       ]
    ELSIF [ or here() ]
    ELSE (or nothing)
  }

答案 2 :(得分:0)

这应该可以工作并捕获括号中的所有文本,包括括号,作为第一个匹配:

/IF(\(.+?\))/

请注意,它与IF()(空括号)不匹配:如果您还要匹配空括号,则可以将+(匹配一个或多个)替换为{{1 (匹配零或更多):

*

---编辑

如果您需要将公式与括号匹配(除了最外面的公式),您可以使用

/IF(\(.*?\))/

这将通过删除 /IF(\(.*\))/ 使正则表达式“不贪婪”。这样它将匹配可能的最长字符串。对不起,我错误地认为你没有任何副括号。

答案 3 :(得分:0)

扩展Paolo的答案,您可能还需要担心空格和案例:

/IF\s*(\(\s*.+?\s*\))/i

答案 4 :(得分:0)

不可能只使用正则表达式。如果您是或可以使用.NET,您应该使用Balanced Matching