用于识别语句的正则表达式

时间:2009-03-16 17:49:27

标签: regex

我正在尝试编写正则表达式来标识if语句。我遇到的唯一问题是如果语句在括号中有括号,则会捕获它。例如:

if (condition_function(params)) {
     statements;
}

我的表达式捕获除了这些之外的所有if语句:

 if\s*\(([^\(\)]|\s)*\)\s*{(.|\s)*?}

有谁知道怎么写?

8 个答案:

答案 0 :(得分:13)

使用正则表达式是不可能的,因为正则表达式只能匹配常规语言,而您尝试解析的语言是无上下文的,不是常规语言(感谢dirkgently和dmckee)。

看看你感兴趣的WP: Formal language theory ......

顺便说一下。如果表达式正确([[][]]正确但[]][不正确),您甚至无法检查仅由括号组成的表达式,这是您上面给出的“子问题”。

答案 1 :(得分:6)

我认为这可行。如果有人看到我没有看到的东西,就像它不起作用的原因,请回复。

if\s*\(((?:[^\(\)]|\((?1)\))*+)\)\s*{((?:[^{}]|{(?2)})*+)}

现在应该遇到的唯一问题是if语句中是否有if语句。

我已经在每一个我能想到的有效if语句上对此进行了测试,这可能会破坏它,并且唯一不起作用的是包含带有不匹配括号的字符串的语句。

更新:我发现上述正则表达式出错。它不会捕获if语句或语句部分中包含具有不匹配括号的字符串的语句。如下例所示:

if (var1 == "("){
    echo "{";
}

然而,这是一个有效的if语句。解决方案:

if\s*\(((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^\(\)]|\((?1)\))*+)\)\s*{((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^{}]|{(?2)})*+)}\s*

这个正则表达式捕获所有if语句,甚至是包含具有不匹配括号的字符串的语句。

更新:我现在拥有它,以便捕获else和if if附加到if语句的语句。唯一的问题是它返回的捕获组是最后一个,如果在if语句中则是最后一个。希望我也能弄清楚如何解决这个问题。

if\s*\(((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^\(\)]|\((?1)\))*+)\)\s*{((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^{}]|{(?2)})*+)}\s*(?:(?:else\s*{((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^{}]|{(?3)})*+)}\s*)|(?:else\s*if\s*\(((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^\(\)]|\((?4)\))*+)\)\s*{((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^{}]|{(?5)})*+)}\s*))*;

如果你想测试一下,这里有一个很棒的网站: http://gskinner.com/RegExr/

答案 2 :(得分:5)

您是否正在尝试编写正则表达式来解析非常规语言?那永远不会飞。

答案 3 :(得分:3)

您需要使用图灵完整语言编写代码。有些工具可以自动为您构建代码,例如Flex。但是,如果您只是遇到一个简单的问题,那么自己编写一些简单的解析代码可能最简单。下面是一些可以帮助您入门的示例C#代码。

public void TestIf()
    {
      var s = @"if (condition_function(params)) {
     statements;
       }";
      var ifRegex = @"if *\(.*\) *{.*}";
      if (Regex.IsMatch(s, ifRegex, RegexOptions.Singleline))
      {
        var firstParens = s.IndexOf('(');
        if (firstParens != -1)
        {
          var conditionPart = s.Skip(firstParens + 1);
          int stack = 1;
          int lastParens = -1; 
          while(stack > 0)
          {
            for (int i = 0; i < conditionPart.Count(); i++)
            {
              var c = conditionPart.ElementAt(i);
              if (c == '(')
              {
                stack++;
              }
              if (c == ')')
              {
                stack--;
              }
              if (stack == 0)
              {
                lastParens = i;
                break; 
              }
            }
          }
          if (lastParens != -1)
          {
            var condition = conditionPart.Take(lastParens);
            Console.WriteLine(new string(condition.ToArray()));
          }
        }
      }
    } 

答案 4 :(得分:1)

r = /\bif\s*\(/

txt = <<TXT
if(test)
if (test)
if  (xyz)
; if
print x if(true)
TXT

p txt.scan(r)

if(something)..某些东西可以是任何东西..如果有一个带有括号结尾的字符串,并且你想要正确处理匹配的括号对,那么你很快就会得到一个很大的正则表达式。

你想用什么语言来对抗?

答案 5 :(得分:0)

如果你必须使用正则表达式,即使它永远不会捕获所有个案,那么这个更好:

if\s*\(((?!\s*\{).+)\)\s*\{(.|\s)*?\}

它使用positive lookahead(?!\s*\{).)确保在结束)之前捕获所有内容(除非您的条件语句中包含“{”!正是regexp无法帮助你的地方)

答案 6 :(得分:0)

快速拍摄......

if\s*?\(.*?)\s*?(({?\s*?(.*?;)+\s*?})|(.*?;))

答案 7 :(得分:-1)

修改正则表达式(Koukaakiva),找不带括号 - https://regex101.com/r/fE6hA5/1 并为模式添加名称