[英]How can I print lines after a regex match in Perl?
我正在通过以下格式的文本文件进行解析
> alpha
apple
airplane
art
> beta
bear
blue
beat
> charlie
cow
cent
coat
我正在尝试查找具有主题(例如“ ta”)的条目( alpha beta charlie
)。 如果找到主题,那么我正在尝试打印出每个条目下方的单词( bear blue beat
)。 所以在这个例子中,我想要以下输出
> beta
bear
blue
beat
我已经弄清楚了如何打印输入行,但是不知道如何打印出下面的行。 任何想法将不胜感激。
my $motif = "ta";
my $file = "file.pl";
open(INPUT, $file) or die "Can't open file.\n";
parse($motif);
sub parse{
my ($x) = (@_);
while(<INPUT>){
if($_ =~ />*($x)/){
print $_."\n";
# if($_ !~ />/){
# print $_."\n";
}else{
next;
}
}
}
这是另一个选择:
use strict;
use warnings;
my $motif = pop;
local $/ = '>'; # record separator
while (<>) {
chomp;
print $/ . $_ if /(?<=\x20).*?$motif/;
}
用法: perl script.pl data.txt 'ta'
在data.txt中的数据上输出:
> beta
bear
blue
beat
local $/ = '>'
符号local $/ = '>'
将记录分隔符设置为>
而不是通常的\\n
,因此每个>
标记读取的记录的开始。 您搜索的行在>
之后紧跟一个空格,这就是正(?<=\\x20)
试图匹配的地方。
您可以通过执行以下操作将输出重定向到文件: perl script.pl data.txt 'ta' >output.txt
。
好吧,您需要保持循环状态。 匹配会触发“打印”状态,而不匹配会触发该状态。 所以你有这样的东西吗?
sub parse {
my ($x) = (@_);
my $printable = 0
while (<INPUT>) {
if ($_ =~ /^>.*($x)/) {
print $_;
$printable = 1;
} elsif ($_ =~ /^>/) {
$printable = 0;
} elsif ($printable) {
print $_;
}
}
}
基本上,您可以使用变量( $print_flag
)来查看是否应打印该行。 如果获得所需的匹配项,则设置为1(评估为true);如果匹配以">"
开头但不包含$motif
的行,则设置为0。
试试这个(警告:未经测试):
use strict; #Always!
use warnings; #Always!
my $motif = "ta";
my $file = "file.pl";
open(my $input,"<", $file) or die $!; #two argument open: bad!
parse($motif);
sub parse{
my ($x) = (@_);
my $print_flag = 0;
while(<$input>){
chomp; #removes trailing EOL character
if(/^>.*($x)/) #Don't need $_
{
$print_flag = 1;
}
elsif(/^>/)
{
$print_flag = 0;
}
if($print_flag)
{
print "$_\n";
}
}
}
对于Perl范围运算符(在这种情况下,通常称为“触发器”运算符)来说,这种类型的问题似乎很自然。 但是,您的要求的详细信息最终使它比我预期的要复杂一些:
#!/usr/bin/env perl
use strict;
use warnings;
parse('ta');
sub parse {
my $pattern = shift;
my $seq;
while (<DATA>) {
if ($seq = /^>.*$pattern/ ... (/^>/ && !/^>.*$pattern/)) {
print unless $seq =~ /E0$/;
}
}
}
__DATA__
> alpha
apple
airplane
art
> beta
bear
blue
beat
> charlie
cow
cent
coat
输出:
> beta
bear
blue
beat
如果比赛之后的行数总是相同(三),那么这个骇人听闻的“比赛倒计时”惯用语将起作用:
perl -ne '$m=4 if (/^>s/ ); print if ($m-->0);'
我们使用"4"
来匹配行及其后的行数( 3
),然后在继续print
以$m--
倒数。 我使用$m
模仿了shell的grep
的类似选项。 但是,实际上我不确定这是否是一个惯用语,或者如果是这样的话,它的接受名称将是什么。 flip-flop
范围...
方法可能是更可取的,或者在脚本中得到了更广泛的使用-但是这里是一个自包含的脚本,可以尝试使用更hackish的方法。
输入行数和模式以作为参数进行搜索:
#!perl
use v5.16; # strict & warnings
my $linesafter ;
my $num = shift ;
my $pat = shift ;
while (<DATA>) {
$linesafter = $num if ( /^> $pat/ );
print if ($linesafter-->0);
}
__DATA__
> alpha
apple
airplane
art
> beta
bear
blue
beat
> charlie
cow
cent
coat
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.