我绞尽脑汁试图找到一个解决方案但是徒劳无功。任何指导将不胜感激。
_data_
mascot
friend
ocean
\n
parsimon
**QUERY**
apple
\n
jujube
\n
apricot
maple
**QUERY**
rose
mahonia
\n
....鉴于搜索关键字是 QUERY ,它会输出:
parsimon
**QUERY**
apple
apricot
maple
**QUERY**
rose
mahonia
我编写的代码无法正常工作:
#!/usr/bin/perl
use strict;
use warnings;
open my $fh, '<', 'FILE' or die "Cannot open: $!";
my @file = <$fh>;
close $fh;
for (0 .. $#file) { # read from the first line to the last
if($file[$_] =~ /QUERY/){ # if the contents of a particular line matches the query pattern
my $start = $_-- until $file[$_--] =~ /^$/; #check the previous line for an empty line. continue until success. store the index of the empty line to $start.
my $end = $_++ until $file[$_++] =~ /^$/; #check the next line for an empty line. continue until sucess. store the index of the empty line to $end.
print "\n @file[$start..$end]"; #print all lines between the stored indexes
}
}
我也尝试了类似的东西,但有句法错误:
if($file[$_] =~ /QUERY/){
my $start = $_-4 if $file[$_-4] =~ /^$/;
continue my $start = $_-3 if $file[$_-3]=~/^$/;
------
my $end = $_+4 until $file[$_+4] =~ /^$/;
.....
print "\n @file[$start..$end]";
}
.....
似乎我迄今为止成功实现的唯一好处是我可以使用以下代码在匹配行和下一行空行之间打印所有内容:
for (0 .. $#file) {
if($file[$_+1] =~ /QUERY/) {
print $file[$_] until $file[$_++]=~/^$/;
有人能指出我正确的方向吗? 谢谢!
麦克
修改
我认为brian d foy解决我的问题是最好的。我认为最有效率。但杰夫的解决方案是最有帮助的,我特别从他详细的逐行解释中得到了很多好处,甚至更好,使用他的代码,只做了一些调整,我可以做其他事情,例如,打印之间的所有行找到模式时以数字开头的行。而Kinopiko的代码是我希望能够编写的代码。
答案 0 :(得分:7)
只需将一行重新定义为一个段落,并在阅读时打印匹配的段落。您可以通过将输入记录分隔符$/
设置为所需的行结尾来更改Perl对行的概念。当您使用行输入操作符时,您将获得所有内容,包括$/
中的内容。有关Perl特殊变量的详细信息,请参阅perlvar:
#!perl
{
local $/ = "\n\n";
while( my $group = <DATA> ) {
print $group if $group =~ /\Q**QUERY**/;
}
}
__DATA__
mascot
friend
ocean
parsimon
**QUERY**
apple
jujube
apricot
maple
**QUERY**
rose
mahonia
ghostdog74发布了他的单行版本,我稍作修改:
perl -ne "$/=qq(\n\n); print if /\Q**QUERY**/" fileA fileB ...
不过, perl有一个特殊的命令行开关。您使用-0
设置输入记录分隔符,如果将其设置为0
,则表示您将其设置为使用段落模式:
perl -00 -ne "print if /\Q**QUERY**/" fileA fileB ...
perlrun向您展示了您可以在命令行上执行的所有精彩内容。
答案 1 :(得分:2)
# more file
mascot
friend
ocean
parsimon
**QUERY**
apple
jujube
apricot
maple
**QUERY**
rose
mahonia
# perl -ne '$/ = "\n\n";print $_ if /QUERY/' file
parsimon
**QUERY**
apple
apricot
maple
**QUERY**
rose
mahonia
答案 2 :(得分:1)
这里有一些“吼叫者”。
这似乎有效:
我的@file =&lt; DATA&gt;
for (0 .. $#file) {
if ($file[$_] =~ /QUERY/){
my $start = $_;
while ($start >= 0 && $file[$start] !~ /^$/) {
$start--;
}
my $end = $_;
while ($end <= $#file && $file[$end] !~ /^$/) {
$end++;
}
print "\n@file[$start+1..$end-1]";
}
}
__DATA__
mascot
friend
ocean
parsimon
QUERY
apple
jujube
apricot
maple
QUERY
rose
mahonia
答案 3 :(得分:1)
这会产生您指定的输出,假设您的意思是“如果找到QUERY,则返回从前一个空白行到下一个空行的所有内容”。如果文件末尾没有空行,则在最后一种情况下会失败,但您可以在while循环后检查最后一个候选项。
#!/usr/bin/perl
use strict;
use warnings;
# Open the file
open my $fh, '<', 'FILE' or die "Cannot open: $!";
# initialize the candidate to an empty string
# This is good form, so we know that we are starting with an empty candidate.
my $candidate = '';
# Go through each line of the file
# The contents of the line will be placed in $_
while(<$fh>) {
# If the line is blank, check the candidate we have accumulated
# This is shorthand for 'if($_ =~ /^$/) {'
if(/^$/) {
# If the candidate contains your QUERY, print it out
# Alternately, you could add it to an array, etc
if($candidate =~ /\nQUERY\n/) {
print "$candidate\n";
}
# We are done with the previous candidate, so clear it out
$candidate = '';
} else {
# If it is not a blank line, concatenate it to your
# candidate. I.e. build up all of the lines between blanks
$candidate .= $_;
}
}
# This handles the final lines, if there is not a blank line
# at the end of the file
if($candidate =~ /\nQUERY\n/) {
print "$candidate\n";
}