Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 搜索文件,找到匹配项后将其存储,然后在上面打印4行,下面打印3行_Perl - Fatal编程技术网

Perl 搜索文件,找到匹配项后将其存储,然后在上面打印4行,下面打印3行

Perl 搜索文件,找到匹配项后将其存储,然后在上面打印4行,下面打印3行,perl,Perl,我有一个简单的搜索脚本,它接受用户输入并在目录和文件之间进行搜索,只列出在其中找到的文件。我想做的是,当找到匹配项时,在上面抓取4行,在下面抓取3行,然后打印出来。所以,假设我有 somefile.html “a;lskdj a;sdkjfa;klsjdf a aa;ksjd a;kjaf;;jk;kj asdfjjasdjfajsd jdjd jdjajsdf ok ok okasdfa stes测试tes测试 废话废话好吧,我保证我的帖子一整天都是真诚的。 尽管有时我会有点粗鲁。 我只会知道

我有一个简单的搜索脚本,它接受用户输入并在目录和文件之间进行搜索,只列出在其中找到的文件。我想做的是,当找到匹配项时,在上面抓取4行,在下面抓取3行,然后打印出来。所以,假设我有

somefile.html
“a;lskdj a;sdkjfa;klsjdf a aa;ksjd a;kjaf;;jk;kj asdfjjasdjfajsd jdjd
jdjajsdf ok ok okasdfa stes测试tes测试
废话废话好吧,我保证我的帖子一整天都是真诚的。 尽管有时我会有点粗鲁。 我只会知道潘多拉的蓝色月亮,如果我看到它,我早就听说了 什么时候…什么的 不管是什么号码76854 正在运行草地等文件==>更多信息 还有什么?”
假设我想找到“76854”,它将打印或存储在一个数组中,这样我就可以打印在dirs/文件中找到的所有匹配项

*Match found:*

**I would only know the blue moon of pandora if I saw it. I heard tales of long ago 
times in which .. blah blah
<some html>whatever whatever</some html>
running thru files of grass etc.. ===> more info
whatever more**


**********************************
*找到匹配项:*
**我只有看到潘多拉的蓝月亮才会知道。我很久以前就听说过这个故事
…的时间。。废话
随便
通过草地等文件运行…==>更多信息
再多**
**********************************
差不多吧。到目前为止,我已经找到了,它正在通过打印找到匹配项的文件来工作:

if ($args->{'keyword'}){
    if($keyword =~ /^\d+$/){
    print "Your Results are as Follows:\n";
        find( sub
            {
                local $/;
                return if ($_ =~ /^\./);
                return unless ($_ =~ /\.html$/i);
                stat $File::Find::name;
                return if -d; #is the current file a director?
                return unless -r; # is the file readable?
                open(FILE, "< $File::Find::name") or return;
                my $string = <FILE>;
                close (FILE);
                print "$keyword\n";
                if(grep /$keyword/, $string){
                    push(@resultholder, $File::Find::name);
                }else{
                   return;
                }
             },'/app/docs/');
    print "Results: @resultholder\n";
    }else{
        print "\n\n ERROR\n";
        print "*************************************\n\n";
        print "Seems Your Entry was in the wrong format \n\n";
        print "*************************************\n\n";
    }
exit;
}
if($args->{'keyword'}){
如果($keyword=~/^\d+$/){
打印“您的结果如下:\n”;
查找(子对象)
{
本地$/;
返回if($);
返回,除非($\=~/\.html$/i);
stat$File::Find::name;
返回-d;#当前文件是否为控制器?
除非返回-r;#文件是否可读?
打开(文件“<$FILE::Find::name”)或返回;
我的$string=;
关闭(文件);
打印“$keyword\n”;
if(grep/$keyword/,$string){
push(@resultholder,$File::Find::name);
}否则{
返回;
}
},“/app/docs/”);
打印“结果:@resultholder\n”;
}否则{
打印“\n\n错误\n”;
打印“********************************************************\n\n”;
打印“您的条目似乎格式错误\n\n”;
打印“********************************************************\n\n”;
}
出口
}

这里perl是先决条件吗?这对于grep来说非常简单,您可以告诉它在匹配前后打印N行

grep file.txt-B-A


如果您真的想使用perl,请忽略这一点,只需抛出一个替代方案。

因此您需要存储至少8行,并在第5行与您的模式匹配时输出这8行。这里,用于从数组前面删除元素的
shift
运算符和用于将元素添加到列表末尾的
push
运算符可能会有所帮助

find( sub {
    ...  # but don't set $\

    open( FILE, '<', $File::Find::name) or return;
    my @buffer = () x 8;
    while (<FILE>) {
        shift @buffer;
        push @buffer, $_;
        if ($buffer[4] =~ /\Q$keyword\E/) {
            print "--- Found in $File::Find::name ---\n";
            print @buffer;
            # return?
        }
    }
    close FILE;

    # handle the case where the keyword is in the last ~4 lines of the file.
    while (@buffer > 5) {
        shift @buffer;
        if ($buffer[4] =~ /\Q$keyword\E/) {
            print "--- Found in $File::Find::name ---\n";
            print @buffer;
        }
    }
} );
查找(子目录){
……但不要设定$\

打开(文件,您使用的是Windows还是Linux

如果您在Linux上,您的脚本最好替换为:

grep -r -l 'search_string' path_to_search_directory
它将列出包含搜索字符串的所有文件。要在匹配行之前获得4行上下文,在匹配行之后获得3行上下文,您需要运行:

grep -r -B 4 -A 3 'search_string' path_to_search_directory
如果出于某种原因您不能或不想使用grep,那么您需要改进您的脚本

首先,使用此结构,您只读取文件中的第一个字符串:

my $string = <FILE>;
my$string=;
第二,最好避免将所有文件读取到内存中,因为可能会遇到几个Gb的文件。甚至可以将一个字符串读取到内存中,因为可能会遇到非常大的字符串。将其替换为对某个小缓冲区的顺序读取


最后,要在找到的匹配之前获得4行,在找到匹配之后获得3行(寻找匹配之前缓冲大小的位置,读取该块并检查其中是否有足够的换行)。

“但是,它不允许在上面获得4行,在下面获得3行。”。您可以通过将
-4
替换为
-b4-a3
来实现这一点。我是一名perl新手,如果可以的话,根据您提供的代码,我有一些问题。1.我的缓冲区=()x 8;做什么?2.移位缓冲区;推送缓冲区,$\u3.$buffer[4]?1.创建一个包含8个空元素的列表。2.从列表中删除第一个元素。3.将元素添加到列表的末尾。4.因为
$buffer[4]
是列表中的第五个元素。即,它前面有4个元素,后面有3个元素。
my $string = <FILE>;