繁体   English   中英

在Perl中进行正则表达式匹配后,如何打印行?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM