如何正确地获取花括号内的代码?

时间:2012-03-30 11:36:22

标签: php regex

我需要某种正则表达式来获取花括号内的部分代码。还有其他问题,但我的有点不同。

将此代码视为示例;

public function my_method($my_input) {
    if(true == false) { $me = "Forever alone. :("; }
    if(true == true) { $me = "No longer alone. :}"; }
    if(false == false) { $me = ":{ - This is so Wrong."; }
}

并忽略“公共函数my_method($ my_input)”部分。我该怎么抓

    if(true == false) { $me = "Forever alone. :("; }
    if(true == true) { $me = "No longer alone. :}"; }
    if(false == false) { $me = ":{ - This is so Wrong."; }

没有被字符串中的“{”和“}”字符(和c的评论等)误导?

我对正则表达式的了解非常有限,而且我很难实现这一点。 :/

3 个答案:

答案 0 :(得分:4)

匹配括号是您不应该尝试使用正则表达式的原型示例之一(即使没有括号内的正则表达式,它也太复杂了)。

这是因为具有嵌套括号的(正式)语言不是常规的,而是由无上下文的语法表示,比简单的正则表达式复杂得多。在非常高的层次上,正则表达式“不能计算到任意大数”,即它们无法识别哪个右括号属于哪个左括号(只要你允许任意嵌套括号的深度 - 比如PHP(至少在原则上) ))。

你应该更好地使用一些支持无上下文语法的工具,甚至可以获得一些已经编写过的PHP解析器。

为了自己提取函数,您应该只查找关键字function(或指示功能块的其他关键字),然后转到左括号({{1 }})。然后,您可以逐个字符地继续,直到找到匹配的右括号({),同时跟踪您当前是否在字符串或注释之内。

但是,我不希望你自己亲自完成这项任务,因为我可以想象,处理所有可能的角落案件会非常麻烦......

答案 1 :(得分:3)

我制作的正则表达式将在大多数情况下通过,即使引号被反斜杠。这是一个示例脚本。我在正则表达式中提供了注释,但请注意我需要在正则表达式中反斜杠,因为我将它用作正则表达式本身的字符串分隔符。

正则表达式是递归的,因此对括号嵌套的深度级数没有限制。但是,括号中不能有错误(即没有匹配的括号),但这是合乎逻辑的猜测。

$str =
'

public function my_method($my_input) {
    if(true == false) { $me = "Forever alone. :("; }
    if(true == true) { $me = "No longer alone. :}"; }
    if(true == true) { $me = \'No longer alone. :}\'; }
    if(true == true) { $me = \'No longer \\\' alone. :}\'; }
    if(false == false) { $me = ":{ - This is so Wrong."; }
}

public function my_method($my_input) {
    if(true == false) { $me = "Forever happy. :("; }
    if(true == true) { $me = "No longer happy. :}"; }
    if(true == true) { $me = \'No longer happy. :}\'; }
    if(true == true) { $me = \'No longer \\\' happy. :}\'; }
    if(false == false) { $me = ":{ - This is so Wrong."; }
}

';

preg_match_all(
   '/
      {                                # opening {
         (                             # matching parentheses
            (?:                        # non matching parentheses
               (?:                     # non matching parentheses
                  [^{}"\']+            # anything but { } " and \'
                  |                    # or
                  "                    # opening "
                     (?:               # non matching parentheses
                        [^"\\\]*       # anything but " and \
                        |              # or
                        \\\"           # a \ followed by a "
                     )*                # as often as possible
                  "                    # closing "
                  |                    # or
                  \'                   # opening \'
                     (?:               # non matching parentheses
                        [^\'\\\\]*     # anything but \' and \
                        |              # or
                        \\\\\'         # a \ followed by a \'
                     )*                # as often as possible
                  \'                   # closing \'
               )*                      # as often as possible
               |                       # or
               (?R)                    # repeat the whole pattern
            )*                         # as often as possible
         )                             # close matching parentheses
      }                                # closing }
   /xs',
   $str,
   $matches
);

print_r($matches);

答案 2 :(得分:2)

正则表达式不是正确的工具 - 有关更多详细信息,请参阅@phimuemue's answer

您可以在脚本中使用PHP's own tokenizer。但是,它不会简单地给你“一些块内的内容”,而是块内的令牌。根据您的要求,您需要从令牌重建源代码。