Answers:
如果使用-r
,则可能只想递归搜索当前目录:
grep -r 'class MyClass' .
请注意上述末尾的句点。
您告诉我们的grep
是,您希望它递归地搜索每个*.php
文件或目录,但是您可能没有任何以.php扩展名结尾的目录。上面是进行搜索的最简单方法,但是还包括其他类型的文件,当您到处都有.svn目录时,这尤其成问题。如果您没有很多其他文件类型,那么上面的内容通常就足够了,并且效果很好。
grep的大多数版本都没有办法指定可以搜索的文件扩展名,因此通常将find与之结合使用:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
告诉某些版本的grep您想执行不区分大小写的文件名搜索,但是find的许多非GNU变体都不支持它,因此您可以改用它-name
。
-exec
上面的选项具有为每个文件调用grep的副作用,这相当昂贵。
grep的其他版本还支持a +
,它告诉find将参数附加在一起以减少可执行文件的调用次数:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
经常推荐的减少调用的方法是使用xargs,它将尽可能少地触发grep,但在必要时可以多次:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
足够聪明,可以将grep传递到命令行上支持的最大参数数目,但是上述变体不能很好地处理某些字符(例如空格)。例如,如果文件名grep使用“ file.php”作为参数,而将“ file.php”作为参数,则不会同时找到这两个文件。相反,我们使用:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
并-0
一起工作,并使用后跟一个空字符的参数,以便完全,明确地标识该参数。
如果您在class
或制表符后有多个空格,则可能需要通过更改正则表达式来允许更多字符:class[ \t]*MyClass
关于StackOverflow的这篇文章还有其他示例,并演示了如何排除某些目录,例如.svn目录。
可能您希望不区分大小写和保留空白,并且grep如果在当前目录中找不到所需文件模式的任何实例,则会终止。它需要知道从哪里开始,并且没有匹配的文件不会产生任何开始路径。
如果至少有一个所需扩展名的文件,则可以使用egrep -ir。 find
并xargs
通过grep失败的单个平面(但非常大)目录和额外的限定符(例如,如果您仅想搜索.inc,.php和php3文件)来显示其功能。但是根据我的经验,它失去了很多便利和速度。对于人类书面的类声明,一个大问题将是空白。因此,请使用egrep而不是grep。另外LC_ALL = C表示额外的速度。为了方便起见,我经常使用:
LC_ALL=C egrep -irn "class[ ]*myclass([ ]|\n)" * | egrep "\.(inc|php[35]?)"
-i -- case insensitive
-r -- recursive for all file pattern (here *)
-n -- include the line number
LC_ALL=C -- search in ASCII, not in utf8, this is much faster.
[ ]* -- match any number of spaces before the class name
([ ]|\n) -- match a space or newline after the classname
这样仍然可以匹配注释,例如// class myclass exists in file
,但是我发现它们相对较小,可以用过滤掉它们。... | fgrep -v '//'
您还可以在egrep文件模式中包括更复杂的文件掩码(例如,以捕获大多数.inc和.php文件),如下所示:
egrep "pattern" *.[ip]*
(使用第一个选项)将非常快,并且主要限于php文件。
高温超导
grep -r
没有得到的东西。