正则表达式在Perl中出错了

时间:2014-05-08 16:46:49

标签: regex perl

我有这段代码:

if ($line =~ /gene_id "([A-Za-z0-9:._]*)";/) {
            $chromosome{$1} = $chompline[0];
            push @{$starts{$1}}, $chompline[3];
            push @{$ends{$1}}, $chompline[4];
            $strand{$1} = $chompline[6];
            $geneid = $1;
            $line =~ /;transcript_id "([A-Za-z0-9:._]*)";/;
            $transcriptid = $1;
        }

此代码读取以下文件:

scaffold_1  Cufflinks   exon    40478   40618   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"
scaffold_1  Cufflinks   exon    40723   40832   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"
scaffold_1  Cufflinks   exon    40944   41016   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"
scaffold_1  Cufflinks   exon    41667   41728   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"
scaffold_1  Cufflinks   exon    42268   42585   .   -   .   gene_id "ppa017353m.g";transcript_id "PAC:17642447";tss_id "TSS3451"
scaffold_1  Cufflinks   exon    43369   43510   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"
scaffold_1  Cufflinks   exon    44834   45052   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"
scaffold_1  Cufflinks   exon    45195   45261   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"
scaffold_1  Cufflinks   exon    47061   47460   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"
scaffold_1  Cufflinks   exon    49006   49153   .   +   .   gene_id "ppa023343m.g";transcript_id "PAC:17657390";tss_id "TSS1"

并且代码适用于除了以下所有行之外的所有行:

scaffold_2  Cufflinks   exon    16897769    16898166    .   -   .   gene_id "ppa018337m.g";transcript_id "PAC:17646596_o.3";tss_id "TSS10299"
scaffold_2  Cufflinks   exon    16899376    16899536    .   -   .   gene_id "ppa018337m.g";transcript_id "PAC:17646596_o.3";tss_id "TSS10299"

例如,我想要以下输出:

ppa023343m.g PAC:17657390

除了我向你展示过的那些线外,它一直都在发生......如果是这些线,我会得到以下结果:

PAC:17646596_o.3 PAC:17646596

这怎么可能?

3 个答案:

答案 0 :(得分:1)

在你的第二个正则表达式中,你说:

$line =~ /;transcript_id "([A-Za-z0-9:._]*)";/;

您允许从azAZ的字符以及所有数字,冒号:,点.并强调_。你的台词有这个东西:

transcript_id "PAC:17646596_o.3";
transcript_id "PAC:17646596_o.3";

正则表达式中你角色组中的所有内容都在那里,所以它们匹配。有下划线和点,还有更多的字母和数字。您的代码完全按照您的要求执行。

也许这种解释可以帮助您更好地理解它:http://regex101.com/r/dE9hJ3


如果您不想在输出中使用_o.3,请将正则表达式更改为:

$line =~ /;transcript_id "([A-Za-z0-9:]*)[^"]*";/;
        #                               ^
        #             notice the ) here ends the capture group

答案 1 :(得分:0)

在使用捕获的变量之前,始终验证正则表达式是否成功。

$transcriptid = $line =~ /;transcript_id "([\w:.]*)";/
    ? $1
    : warn "transcript_id didn't match: $line";

或者,您也可以将正则表达式匹配加入到单个语句中,因此只需要进行一次错误检查:

if ($line =~ /gene_id "([\w:.]*)";transcript_id "([\w:.]*)";/) {
    ($geneid, $transcriptid) = ($1, $2);

    $chromosome{$geneid} = $chompline[0];
    push @{$starts{$geneid}}, $chompline[3];
    push @{$ends{$geneid}}, $chompline[4];
    $strand{$geneid} = $chompline[6];

} else {
    warn "Regex didn't match: $line\n"
}

答案 2 :(得分:-1)

您需要转义句点等字符,否则它将匹配任何内容。另外,让单个正则表达式捕获两个数据(根据您发布的代码而不知道您的意图是什么)更有意义:

if ($line =~ /gene_id "([^\"]*)";transcript\_id\s\"(PAC:[^\"]*)\"/ ) {
    $geneid = $1;
    $transcriptid = $2;
}

编辑:链接到正则表达式演示:http://regex101.com/r/wK1gF8