如何使用grep在PHP文件中搜索字符串?


11

我正在搜索包含数百个PHP文件的网站上的类声明。如何使用grep在当前文件夹和子文件夹中执行此操作?

我测试cd到文件夹,然后像

grep -r 'class MyClass' *.php

当这迁移到超级用户时,您可能想说些您grep -r没有得到的东西。

我很困惑-你不只是回答自己吗?那条线的结果是什么?您是否正在尝试进一步优化?请设想将这个问题与其他人一起阅读,因为它令人困惑且不清楚。
meder omuraliev

@其他评论:他的grep -r语句没有给出他想要的内容,除非所有文件夹都以.php结尾,但事实并非如此……
David Oneill 2010年

我什么都没得到。我认为它没有用,因为我知道它是在具有此类文件的文件夹中的im上找到的

我很幸运地找到了文件。在带有该行的PHP文件的文件夹中搜索文件时,它将找到它(不需要-r)。如果我将CD复制到根目录并使用递归-r进行搜索,则不会返回任何内容。

Answers:


24

你可以试试

grep -r --include=*.php "search string" /path/to/dir

1
效果很好。我一直忘了,但幸运的是,总有这个答案再次对我有所帮助。:)
GolezTrol

@GolezTrol很高兴知道:-)
rahul286

9

我建议您使用ctags之类的东西,而不要使用grep。但是,如果您愿意,可以执行类似的操作

 find <top level dir> -name \*.php | xargs grep "class MyClass"

当然,这假定您之间只有一个空格,classmyClass这可能不是正确的。更改正则表达式以查找任意数量的空格很容易。


4

如果使用-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目录。


这将搜索所有文件。也是不是.php文件的文件。
GolezTrol,2014年

我已经更新了帖子,以包括许多其他示例。
Kaleb Pederson 2014年


1
grep -r 'class MyClass' *.php

将搜索所有名称以.php结尾的文件夹

grep -r 'class MyClass' . | grep .php

将在所有子文件夹中的所有文件中搜索类MyClass,然后仅返回其中包含.php的类。


1

find . -type f -name *.php -print -exec grep \"class MyClass\" {} \; 将为您提供其所在行的内容以及文件的路径。


1

如果匹配的文件可能具有任意名称,则应考虑使用 -print0

找 。-type f -name'* .php'-print0 | xargs -0 grep'class MyClass'


1
grep -rl 'class MyClass' . --include \*.php

l仅显示文件名

r是递归的

。在当前文件夹中搜索

--include限制文件扩展名


1

可能您希望不区分大小写和保留空白,并且grep如果在当前目录中找不到所需文件模式的任何实例,则会终止。它需要知道从哪里开始,并且没有匹配的文件不会产生任何开始路径。

如果至少有一个所需扩展名的文件,则可以使用egrep -ir。 findxargs通过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文件。

高温超导


0

我知道它说使用grep,但是我个人最喜欢使用ack-grep

ack-grep "class MyClass"

它以递归方式运行,列出查找结果的文件名,并在其中找到行号并突出显示。要专门针对php文件,您可以运行:

ack-grep --type-set php:ext:php "path"

该软件包有很多选择。我绝对会推荐它(并浏览其相关的手册页)来做一些奇特的事情。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.