Как сделать grep, чтобы составить список всех классов PHP из всех файлов?

Я пытаюсь grep все файлы, содержащие имена классов, например:

$ grep -ER "(^| )class [^ ]*" .

Где я думал (^| ) будет включать в себя либо пробел, либо перевод строки, но он показывает все классные слова в комментариях, такие как:

./includes/bootstrap.inc: *   The name of the class to check or load.

И следующий пример:

grep -ER "(^|\?abstract)class [^ ]*" .

на самом деле не содержит никаких абстрактных файлов классов.

В основном я пытаюсь сделать регулярные выражения, такие как:

  1. Новая строка или пробел.
  2. Необязательное слово abstract,
  3. class имя (слово).
  4. Пространство после него.
  5. Любое фактическое имя класса (слово).

Таким образом, регулярное выражение будет реагировать на следующие строки:

  class Entity {
class Entity {
class NoFieldsException extends Exception {}
abstract class CacheArray implements ArrayAccess {

Но не для этого:

 * This class should be extended by systems that need to cache large amounts

Настройка среды тестирования:

$ curl -o- http://ftp.drupal.org/files/projects/drupal-7.31.tar.gz | tar zxf - && cd drupal-7*
$ grep -ER "(^| )class [^ ]*" . | less
$ grep -ER "(^|\?abstract)class [^ ]*" . | wc -l
653 # But this doesn't include ./includes/bootstrap.inc:abstract class DrupalCacheArray

Примеры использования:

  • В случае, если реестр класса Drupal CMS не работает, стол должен быть восстановлен, поэтому все доступные файлы, содержащие классы, должны быть импортированы в таблицу SQL.

2

Решение

Как упоминает Аркаша, вероятно, существует слишком много возможностей сделать это с помощью регулярных выражений, однако, учитывая ваши примеры, это должно сработать для них:

/^(\s+)?(abstract\s+)?class\s+(\S+)/igm

Посмотрите это в действии: http://regex101.com/r/qM7iO0/4

1

Другие решения

Альтернатива моему другому ответу — позволить PHP справиться с этим без фактического выполнения кода с использованием токенизатор. Таким образом, у вас не должно быть никаких негативных побочных эффектов неправильного регулярного выражения, так как PHP выполняет весь анализ.

test1.php:

<?php

$source = file_get_contents('test2.php');
$tokens = token_get_all($source);

foreach ($tokens as $token) {
// 308 is for classes
if ($token[0] == 308) {
// $token[1] contains the actual class name
echo $token[1] ."\n";
}
}

test2.php:

  class Entity { }
class                                             Entity {
}
class NoFieldsException extends Exception {}
abstract
class
CacheArray implements ArrayAccess { }
// But not for these:

/* This class should be extended by systems that need to cache large amounts */

Выход:

Entity
Entity
NoFieldsException
Exception
CacheArray
ArrayAccess

Обратите внимание, что может быть нежелательно иметь Exception а также ArrayAccess и здесь, так как один является родным классом PHP, а другой реализуется. Если нет, попробуйте сделать print_r($tokens); и играть с ним, чтобы получить то, что вы хотите. Вы также можете добавить их все в массив, а затем сделать array_unique() чтобы получить уникальные значения.

2