3

本质上,我要做的是搜索一个大文本文件以识别每个显示“未找到匹配项",并将匹配的标识符复制到一个新列表中。我对第一部分很好,但我似乎无法弄清楚如何将数组的元素精确地复制回 5 个索引(这是一个标识符)并将其复制到不同的数组。

我尝试过这样的事情,

$fastafile = 'HpHcTEST.txt';
open(FASTAFILE, $fastafile);
@seq = <FASTAFILE>;
my $fastaid;
foreach (@seq) {
    if ($_ =~ /\*\*\*\*\* No hits found \*\*\*\*\*/){
        $fastaid .= $_[-5];
    }
}

print "here are the IDs\n";
print $fastaid;

有大量的 [-5] 变体,但没有一个起作用.. 我似乎找不到任何关于如何回溯引用并在满足匹配时获得前一个元素的文档。有人知道如何为此编码吗?

非常感谢您的宝贵时间。

安德鲁

4

4 回答 4

3

您可以遍历索引和下标以获取数组元素:

for (5..$#seq) {
    $fastaid .= $seq[$_-5] if $seq[$_] =~ /your_regex/;
}

在 Perl 5.12 或更高版本中,您还可以使用each

while (my ($index, $value) = each @seq) {
    next if $index < 5;
    $fastaid .= $seq[$index-5] if $value =~ /your_regex/;
}
于 2012-04-24T21:15:52.500 回答
3

快速修复

@seq一种方法是带着索引走过去。

my @fastaid;

for (my $i = 0; $i < @seq; ++$i) {
    if ($seq[$i] =~ /\*\*\*\*\* No hits found \*\*\*\*\*/){
        push @fastaid, $seq[$i - 5] if $i >= 5;
    }
}

请注意从标量更改为名为 的数组@fastaid,您可以使用它打印

print "Here are the IDs:\n";
print "  - $_\n" for @fastaid;

甚至

print "Here are the IDs:\n",
      map "  - $_\n", @fastaid;

添加抛光剂

正如brian d foy下面评论中的注释,代码可以更优雅,更直接地表达意图。

my $id_offset = 5;
my @fastaid;

for ($id_offset .. $#seq) {
    if ($seq[$_] =~ /\*\*\*\*\* No hits found \*\*\*\*\*/){
        push @fastaid, $seq[$_ - $id_offset];
    }
}

perldata 的“标量值”部分所述$#seq是索引或@seq. ..范围运算符正确处理长度@seq小于$id_offset元素的情况。

显式的 regex-bind 运算符仍然有点不靠谱。你可以和

my $id_offset = 5;
my @fastaid;

for my $i ($id_offset .. $#seq) {
  for ($seq[$i]) {
    push @fastaid, $seq[$i - $id_offset]
      if /\*\*\*\*\* No hits found \*\*\*\*\*/;
  }
}

或者如果您至少有 5.10 版

use feature 'switch';

# ...

my $id_offset = 5;
my @fastaid;

for my $i ($id_offset .. $#seq) {
  given ($seq[$i]) {
    when (/\*\*\*\*\* No hits found \*\*\*\*\*/) {
      push @fastaid, $seq[$i - $id_offset];
    }
  }
}

历史记录

过去,有一些关于重新定位$#以跟踪数组遍历的索引的讨论,因此您可以编写

for (@fastaid) {
    if (/\*\*\*\*\* No hits found \*\*\*\*\*/) {
        push @fastaid, $seq[$# - 5] if $# >= 5;
    }
}

但这从未实现。

于 2012-04-24T21:12:24.967 回答
2
my @fasta_id = map { $seq[$_] =~ /your_regex/ ? $seq[$_-5] : () } 5 .. $#seq;
于 2012-04-25T06:59:56.520 回答
-2

使用“for”循环而不是“foreach”,

for ($index=0; $index < $#seq + 1; $index++) {
    if ($seq[$index] =~ /\*\*\*\*\* No hits found \*\*\*\*\*/){
        $fastaid .= $seq[$index-5];
    }
}
于 2012-04-24T21:19:01.737 回答