开发者

Perl Grep multiple patterns

I have a file lets say it is called

                                 filename.c

I am trying to find if the file is being used in one of the following ways

                          1.  include("filename.c");
                          2.   require("filename.c");
                          3.   x = new filename() ; 
                          4.   class new_class extends filename
           开发者_开发知识库               5.   class new_class implements filename
                          6.   filename::function()

I am wondering if perl will allow me to do all the above search at once or I just have to do them one by one?

And also I am not very good at regular expressions so I am wondering how can I grep the string extends filename implement filename

the space in between is giving me problems. Thanks in advance.


what is wrong with grep?

W="filename"
find . -type f -print0 | xargs -0 grep -ilP "include(\"$W\.c\")|require(\"$W\.c\")|x\s*=\s*new\s+$W()|class\s+new_class\s+extends\s+$W|class\s+new_class\s+implements\s+$W|$W::function()"


Use File::Find

I've tried to compile a complete example for you. But, you say you aren't very good at regular expressions, so though I've included all of the matches you said you need, you could eliminate them one by one till you understand what's going on.

You could save this script in a file, say script.pl, and call it like this:

perl script.pl dir1 dir2 and dir1 and dir2 will be deeply searched. The wanted sub will be called on all files and directories, but I've added a check to return immediately if the current entry ($_) is a directory.

NOTE: Because I added /x to the regex you can add whitespace to break up the regex on multiple lines so that it's easier to read. You may want to add /i if you need case-insensitive searching.

use strict;
use warnings;
use File::Find;

my $filename_to_check = 'filename'; ## or you could set it as first arg and say
                                    ## my $filename_to_check = shift @#ARGV;
my $filename_check = qr/(?:
            include\s*\(\s*"$filename_to_check\.c"\s*\)|
            require\s*\(\s*"$filename_to_check\.c"\s*\)|
            new\s+$filename_to_check\s*\(|
            class\s+\S+\s+extends\s+$filename_to_check|
            class\s+\S+\s+implements\s+$filename_to_check|
            $filename_to_check\::[\w]+\s*\(\s*\)
        )/x;

&find(\&wanted,@ARGV); ## where ARGV has all the directories you want to search

sub wanted
{
    ## don't try to open directories like files
    ## you can also return (exit wanted for current file) based on file extension.
    ##    or other arbitrary reasons.
    return if -d $_;

    eval
    {
        open F,$_ || die "Can't read $File::Find::name, $!\n";
        my $found = 0;
        while(<F>)
        {
            if($_ =~ $filename_check)
            {
                $found ++;
                print $_;
            }
        }
        if($found)
        {
            print "Found $found matches in file, $File::Find::name\n";
        }
    };
    if($@)
    {
        print STDERR $@;
    }
}


I think you're looking for |, the regex "or" operator.

/include\("filename\.c"\);|require\("filename\.c"\);|x = new filename\(\) ;|class new_class extends filename|class new_class implements filename|filename::function\(\)\*/


For "class BLAH extends FOO" you might want something like

/class\s+\S+\s+extends\s+\S+/
  • \s matches any kind of whitespace,
  • \S matches any kind of non-whitespace,
  • the + suffix means "one or more of", so "\s+" means "one or more whitespace".
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜