RegEx Удаление методов из кода - PullRequest
4 голосов
/ 07 февраля 2010

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

<?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().

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

Ответы [ 2 ]

6 голосов
/ 07 февраля 2010

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

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

Вот небольшая демонстрация того, как использовать функцию токенизатора, упомянутую XUE 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();



?>

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

3 голосов
/ 07 февраля 2010

Я считаю, что использование встроенной в PHP функции Tokenizer или Zend_CodeGenerator из Zend Framework является более безопасным способом. Это также сделает ваш код более читабельным.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...