Perl 正则表达式 - 在匹配前后获取文本

Perl Regex - Getting Text Before and After Match

我正在逐行解析制表符分隔的文件:

Root rootrank 1 Bacteria domain .72 Firmicutes phylum 1 Clostridia class 1 etc.

=

while (my $line = <$fh>) {
    chomp($line);
}

在每一行中,我都想捕获特定匹配前后的第一个条目。例如,对于匹配 phylum,我想捕获条目 Firmicutes1。对于匹配 domain,我想捕获条目 Bacteria.72。我将如何编写正则表达式来执行此操作?

旁注:我不能简单地将一行一行地拆分成一个数组并使用索引,因为有时会丢失一个类别或有额外的类别,这会导致条目移动一个或两个索引。我想避免编写 if 语句块。

您仍然可以拆分输入,然后将单词映射到索引,然后使用与匹配对应的索引来提取相邻单元格:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my @matches = qw( phylum domain );

while (<>) {
    chomp;
    my @cells = split /\t/;
    my %indices;
    @indices{ @cells } = 0 .. $#cells;
    for my $match (@matches) {
        if (defined( my $index = $indices{$match} )) {
            say join "\t", @cells[ $index - 1 .. $index + 1 ];
        }
    }
}

缺少什么:

  1. 您应该处理 $index == 0 或 $index == $#cells 的情况。
  2. 你应该处理一些单词在一行中重复的情况。

您可以简单地使用以下 regex 来捕获匹配词的词 beforeafter

(?<LSH>[\w.]+)[\s\t](?<MATCH>.*?)[\s\t](?<RHS>[\w.]+)

demo / explanation

你可以这样做:

#!/usr/bin/perl
use Modern::Perl;

my @words = qw(phylum domain);
while(<DATA>) {
    chomp;
    for my $word (@words) {
        my ($before, $after) = $_ =~ /(\S+)(?:\t\Q$word\E\t)(\S+)/i;
        say "word: $word\tbefore: $before\tafter: $after";
    }
}

__DATA__
Root rootrank 1 Bacteria domain .72 Firmicutes phylum 1 Clostridia class 1 etc.

输出:

word: phylum    before: Firmicutes  after: 1
word: domain    before: Bacteria    after: .72
 my $file = "file2.txt";
 open my $fh, '<', $file or die "Unable to Open the file $file for reading: $!\n";
 while (my $line = <$fh>) {
     chomp $line;
     while ($line =~ /(\w+)\s+(\w+)\s+(\.?\d+)/g) {
     my ($before, $match, $after) = (, , );
     print "Before: $before  Match: $match  After: $after\n";
   }
}