【问题标题】:How to grep to make the list of all PHP classes from all the files?如何 grep 从所有文件中列出所有 PHP 类?
【发布时间】:2014-10-14 19:11:35
【问题描述】:

我正在尝试 grep 包含类名的所有文件,例如:

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

我认为(^| ) 会包含either whitespace or newline,但它显示了 cmets 中的所有类词,例如:

./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

示例用例:

【问题讨论】:

  • 您应该使用之前的正则表达式来清除 cmets、非 php 部分和字符串。那么提取类名就很简单了。
  • 这永远不会可靠地工作。可能的故障点太多。另一种策略呢:查找所有文件,然后依次包含,如果成功比较文件加载前后定义的类列表。应该更精确,但速度较慢。
  • 很难说具体的行是否是评论本身,因为可能包含*,或者不能。所以在class字之前排除多个字或仅限于一个特殊字(例如abstract)我认为应该做得更好。

标签: php regex command-line grep


【解决方案1】:

我的另一个答案的替代方法是允许 PHP 处理它而无需使用 tokenizer 实际执行代码。这样你就不应该有任何不正确的正则表达式的负面影响,因为 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

注意,ExceptionArrayAccess 也可能不希望出现在这里,因为其中一个是原生 PHP 类,而另一个正在实现中。如果没有,请尝试使用print_r($tokens); 并使用它来获得您想要的东西。您也可以将它们全部添加到数组中,然后执行 array_unique() 以获取唯一值。

【讨论】:

    【解决方案2】:

    正如 arkascha 所提到的,使用正则表达式完成此操作的可能性可能太多,但是鉴于您拥有的示例,这应该适用于他们:

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

    查看实际操作:http://regex101.com/r/qM7iO0/4

    【讨论】:

    • 谢谢,它似乎有效,grep -ER "^(\s+)?(abstract )?class (\S+)" . 巧合地发现了 666 个类:)
    • @kenorb 我也更新了它以匹配单词之间是否有多个空格和/或换行符。再次尝试运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多