此代码从我拥有的文本文件中获取关键字“fun”,然后在关键字之前和之后打印20个字符。但是,我还希望它打印前两行和接下来的两行,我不知道该怎么做。我不确定用这个更改代码是否更容易,或者只是一次读取整个文件。
{my $inputfile = "file";
$searchword = 'fun';
open (INPUT, '<', $inputfile) or die "fatal error reading the file \n";
while ($line1=<INPUT>)
{
#read in a line of the file
if ($line1 =~m/$searchword/i)
{print "searchword found\n";
$keepline = $line1;
$goodline =1;
$keepline =~/(.{1,20})(fun)(.{1,20})/gi;
if ($goodline==1)
{&write_excel};
$goodline =0;
}
答案 0 :(得分:0)
您的代码似乎
$searchword
的每一边取20个字符; $searchword
,则$goodline
无条件设置为&#39; 1&#39;然后测试看它的&#39; 1&#39;最后重置为&#39; 0&#39; 把它放在一边,关于是否读取整个文件的问题取决于你的具体情况 - 你要搜索的文件有多大,你的机器有足够的内存;机器是共享资源等等。我认为你可以在整个档案中读到,因为这是我经历中更常见的立场(那些不同意的人请记住(a)我承认它有争议;以及(b)它非常依赖于只有OP知道的情况
鉴于此,有几种方法可以读取整个文件,但consensus seems to be可以使用模块File::Slurp
。鉴于这些参数,答案看起来像这样;
#!/usr/bin/env perl
use v5.12;
use File::Slurp;
my $searchword = 'fun';
my $inputfile = "file.txt";
my $contents = read_file($inputfile);
my $line = '\N*\n';
if ( $contents =~ /(
$line?
$line?
\N* $searchword \N* \n?
$line?
$line?
)/x) {
say "Found:\n" . $1 ;
}
else {
say "Not found."
}
如果文件不存在(或出现其他问题), File::Slurp
会输出合理的错误消息,因此我遗漏了典型的or die...
。每当使用正则表达式时 - 特别是如果你试图在多行上匹配东西,那么使用&#34;扩展模式&#34; (在最后的&#39; /&#39;之后加上&#39; x)以允许正则表达式中的无关紧要的空格。这样可以实现更清晰的布局。
我还将行的定义分开,以增加清晰度,其中包含0个,1个或多个非换行符\N*
,后跟新行\n
。但是,如果您的目标位于第一行,第二行,倒数第二行或最后一行,我认为您仍然需要该信息,因此可选地匹配所请求的前后行对。 $line?
请注意,正则表达式是迂腐的,并且不可避免地存在细节和细节。这会影响成功匹配与不想要的匹配的定义 - 即。不要期望在所有情况下都能做到完全你想要的东西。期待你必须尝试和调整一些东西。
答案 1 :(得分:0)
我不确定我是否理解你的代码块(“承诺”的目的是什么?&write_excel
是什么?),但我可以自己回答你的问题。
首先,这个grep命令是否可以接受?它更快更清洁:
grep -i -C2 --color "fun" "file"
-C NUM
标志告诉grep
提供围绕每个模式匹配的NUM行上下文。显然,--color
是可选的,但它可以帮助您在很长的行上找到匹配项。
否则,这里有一点perl:
#!/usr/bin/perl
my $searchword = "fun";
my $inputfile = "file";
my $blue = "\e[1;34m"; # change output color to blue
my $green = "\e[1;32m"; # change output color to green
my $nocolor = "\e[0;0m"; # reset output to no color
my $prev1 = my $prev2 = my $result = "";
open (INPUT, '<', $inputfile) or die "fatal error reading the file \n";
while(<INPUT>) {
if (/$searchword/i) {
$result .= $prev2 . $prev1 . $_; # pick up last two lines
$prev2 = $prev1 = ""; # prevent reusing last two lines
for (1..2) { # for two more non-matching lines
while (<INPUT>) { # parse them to ensure they don't match
$result .= $_; # pick up this line
last unless /$searchword/i; # reset counting if it matched
}
}
} else {
$prev2 = $prev1; # save last line as $prev2
$prev1 = $_; # save current line as $prev1
}
}
close $inputfile;
exit 1 unless $result; # return with failure if without matches
$result =~ # add colors (okay to remove this line)
s/([^\e]{0,20})($searchword)([^\e]{0,20})/$blue$1$green$2$blue$3$nocolor/g;
print "$result"; # print the result
print "\n" unless $result =~ /\n\Z/m; # add newline if there wasn't already one
错误:这假设之前的两行和之后的两行实际上是20多个字符。如果你需要解决这个问题,它会进入else
节。