我有一个简单的搜索脚本,可以在目录和用户之间进行用户输入和搜索。文件,只列出它找到的文件。我想要做的是能够找到匹配,在它上面抓4行,在它下面3行并打印它。所以,让我说我有。
"a;lskdj a;sdkjfa;klsjdf a aa;ksjd a;kjaf ;;jk;kj asdfjjasdjjfajsd jdjd
jdjajsdf<blah></blah> ok ok okasdfa stes test tes tes test test<br>
blah blah blah ok, I vouch for the sincerity of my post all day long.
Even though I can sometimes be a little crass.
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 some number 76854</some html>
running thru files of grass etc.. ===> more info
whatever more "
并且假设我想找到“76854”它会打印或存储在数组中,这样我就可以打印在dirs / files中找到的所有匹配项。
*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;
}
答案 0 :(得分:3)
perl是先决条件吗?使用grep这很容易,你可以告诉它在匹配前后打印N行。
grep <search-term> file.txt -B <# of lines before> -A <# of lines after>
请忽略你是否真的想要使用perl,只是抛出一个替代品。
答案 1 :(得分:3)
您使用的是Windows还是Linux?
如果你在Linux上,你的脚本最好用以下代码替换:
grep -r -l 'search_string' path_to_search_directory
它会列出包含search_string的所有文件。要获得前面的4行上下文和行匹配后的3行,您需要运行:
grep -r -B 4 -A 3 'search_string' path_to_search_directory
如果由于某种原因你不能或不想使用grep,你需要改进你的脚本。
首先,使用这种结构,您只能读取文件中的第一个字符串:
my $string = <FILE>;
其次,你最好避免将所有文件都读到内存中,因为你可以遇到几个Gb文件。甚至读一个字符串到内存,因为你可以遇到真正的大字符串。将其替换为顺序读取到一些小缓冲区。
最后一个,在你需要从找到的匹配中执行反向读取之前得到4行和3行之后(在匹配之前寻找到buffer_size的位置,读取该块并检查是否有足够的换行符)在它)。
答案 2 :(得分:2)
因此,您需要存储至少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;
}
}
} );