2010-02-07 4 views
4

С регулярными выражениями Я пытаюсь удалить все методы/функции из следующего кода. Выход из «глобального масштаба» один. Тем не менее, я не могу заставить его соответствовать всему внутреннему содержимому метода.Способы удаления RegEx из кода

<?php 
$mother = new Mother(); 
class Hello 
{ 
    public function FunctionName($value="username",) 
    { 

    } 
    public function ododeqwdo($value='') 
    { 
     # code... 
    } 
    public function ofdoeqdoq($value='') 
    { 
    if(isset($mother)) { 
     echo $lol; 
    } 
    if(lol(9)) { 
     echo 'lol'; 
    } 
    } 
} 
function user() 
{ 
    if(isset($mother)) { 
     echo $lol; 
    } 
    if(lol(9)) { 
     echo 'lol'; 
    } 
} 
    $mother->global(); 
function asodaosdo() { 

} 

В настоящее время регулярные выражения у меня есть: (?:(public|protected|private|static)\s+)?function\s+\w+\(.*?\)\s+{.*?} Однако, это не будет выбрать метод, который имеет скобки внутри, как function user().

Если кто-то может указать мне в правильном направлении.

+0

Получить парсер. – kennytm

+0

Любой парсер, которого вы знаете, что позволит мне сделать это без особых проблем? – MarioRicalde

ответ

6

Вы не можете сделать это правильно с регулярным выражением. Вам нужно написать синтаксический анализатор, который может правильно анализировать комментарии, строковые литералы и вложенные скобки.

Regex не могут справиться с этими случаями:

class Hello 
{ 
    function foo() 
    { 
    echo '} <- that is not the closing bracket!'; 
    // and this: } bracket isn't the closing bracket either! 
    /* 
    } and that one isn't as well... 
    */ 
    } 
} 

EDIT

Вот небольшая демонстрация того, как использовать функцию Tokenizer упоминаемый Сюэ Can:

$source = <<<BLOCK 
<?php 

\$mother = new Mother("this function isNotAFunction(\$x=0) {} foo bar"); 

class Hello 
{ 
    \$foo = 666; 

    public function FunctionName(\$value="username",) 
    { 

    } 
    private \$bar; 
    private function ododeqwdo(\$value='') 
    { 
     # code... 
    } 
    protected function ofdoeqdoq (\$value='') 
    { 
     if(isset(\$mother)) { 
      echo \$lol . 'function() {'; 
     } 
     if(lol(9)) { 
      echo 'lol'; 
     } 
    } 
} 

function user() 
{ 
    if(isset(\$mother)) { 
     echo \$lol; 
    } 
    /* comment inside */ 
    if(lol(9)) { 
     echo 'lol'; 
    } 
} 
/* comment to preserve function noFunction(){} */ 
\$mother->global(); 

function asodaosdo() { 

} 

?> 
BLOCK; 

if (!defined('T_ML_COMMENT')) { 
    define('T_ML_COMMENT', T_COMMENT); 
} 
else { 
    define('T_DOC_COMMENT', T_ML_COMMENT); 
} 

// Tokenize the source 
$tokens = token_get_all($source); 

// Some flags and counters 
$tFunction = false; 
$functionBracketBalance = 0; 
$buffer = ''; 

// Iterate over all tokens 
foreach ($tokens as $token) { 
    // Single-character tokens. 
    if(is_string($token)) { 
     if(!$tFunction) { 
      echo $token; 
     } 
     if($tFunction && $token == '{') { 
      // Increase the bracket-counter (not the class-brackets: `$tFunction` must be true!) 
      $functionBracketBalance++; 
     } 
     if($tFunction && $token == '}') { 
      // Decrease the bracket-counter (not the class-brackets: `$tFunction` must be true!) 
      $functionBracketBalance--; 
      if($functionBracketBalance == 0) { 
       // If it's the closing bracket of the function, reset `$tFunction` 
       $tFunction = false; 
      } 
     } 
    } 
    // Tokens consisting of (possibly) more than one character. 
    else { 
     list($id, $text) = $token; 
     switch ($id) { 
      case T_PUBLIC: 
      case T_PROTECTED: 
      case T_PRIVATE: 
       // Don'timmediately echo 'public', 'protected' or 'private' 
       // before we know if it's part of a variable or method. 
       $buffer = "$text "; 
       break; 
      case T_WHITESPACE: 
       // Only display spaces if we're outside a function. 
       if(!$tFunction) echo $text; 
       break; 
      case T_FUNCTION: 
       // If we encounter the keyword 'function', flip the `tFunction` flag to 
       // true and reset the `buffer` 
       $tFunction = true; 
       $buffer = ''; 
       break; 
      default: 
       // Echo all other tokens if we're not in a function and prepend a possible 
       // 'public', 'protected' or 'private' previously put in the `buffer`. 
       if(!$tFunction) { 
        echo "$buffer$text"; 
        $buffer = ''; 
       } 
     } 
    } 
} 

, который будет печать:

<?php 

$mother = new Mother("this function isNotAFunction($x=0) {} foo bar"); 

class Hello 
{ 
    $foo = 666; 


    private $bar; 


} 


/* comment to preserve function noFunction(){} */ 
$mother->global(); 



?> 

, который является исходным источником, только без функций.

+0

Большое спасибо за то, что нашли время, чтобы на самом деле дать мне отличный пример. +1 и ответ – MarioRicalde

+0

Добро пожаловать в kuroir. Сделайте также голосование XUE Ответьте, если вы еще этого не сделали: из-за его поста я опубликовал эту небольшую демоверсию. Будучи новичком PHP, я никогда не слышал о функции 'token_get_all (...)'. –

+0

Прохладный пример! Спасибо, Барт. –

3

Я считаю, что использование функции PHP's built-in Tokenizer или Zend_CodeGenerator из Zend Framework является более безопасным способом. Они также сохранят ваш код более читаемым.

Это просто потому, что если вы хотите использовать регулярное выражение для анализа исходных кодов, вы должны сохранить свои собственные жетоны, но есть встроенное решение.

Смежные вопросы