弄清楚正确的匹配正则表达式

时间:2014-11-19 18:58:13

标签: regex perl

我对编程比较陌生。我目前正在学习Perl,我遇到了一个逻辑问题,导致我无法正确完成脚本。任何帮助将不胜感激!!提前感谢您的有用见解!

该程序的大部分内容已经编写完成,这是让我头疼的最后一步。

我有一个变量$RNA,它以任何顺序获得核苷酸序列(acgu)。例如:

$RNA = agcuaggaaggguuuugauag

等等。

我已经创建了一个散列,其中每3个核苷酸的字符或密码子(例如uga)被分配给一个确定的氨基酸。 E.g:

% my AminoAcid   = (
  ggg => "G",
  ...
);

我想做的是在aug字符串中读取START CODON $RNA时打印与哈希中密码子对应的已定义氨基酸(大写字母)每当它读取STOP CODON uga时,停止打印哈希中定义的氨基酸。

例如:假设$RNA = aaaaugcccgggugaccccccccc。程序应打印相应的氨基酸(aug),并在读取字符串中的终止密码子(uga)时停止。

注意:它应该在读取START密码子(aaa)之前忽略前三个aug,并且在读取终止密码子(ccccccccccccc)之后忽略uga并且如果它再次在字符串中的任何位置看到起始密码子aug,则重复相同的过程。

我尝试了多个想法,但没有一个能够描绘出为最后一部分编写代码的正确方法。我可能没有完全掌握它背后的逻辑。

非常感谢任何帮助。在此先感谢!!!

3 个答案:

答案 0 :(得分:1)

让我们从这开头:

my $rna = "aaaaugcccgggugaccccccccc";
my %aminoAcidMap = ( ggg => "G", ccc => "C" );

第一步是提取auguga之间的相关部分:

$rna =~ /aug((?:[acgu]{3})*?)uga/ or die;
my $pattern = $1;

这假设aug可以出现在字符串中的任何位置。此外,它确保如果它跨越两个密码子,是否不会停留在uga

如果您要求起始密码子位于可被3整除的字符串中的索引处,则可以改为:

$rna =~ /^(?:[acgu]{3})*?aug((?:[acgu]{3})*?)uga/ or die;
my $pattern = $1;

此时,$pattern将包含auguga之间的部分。

现在,要进行映射,您可以这样做:

my $aminoAcids = $pattern =~ s/[acgu]{3}/$aminoAcidMap{$&}/ger;

这将用散列中的值替换每个密码。

如果你把所有东西打包成一个子,你得到:

sub getAminoAcids {
    local ($_) = @_;
    /aug((?:[acgu]{3})*?)uga/ or return "";
    $1 =~ s/[acgu]{3}/$aminoAcidMap{$&}/ger;
}

答案 1 :(得分:1)

这可能有效,将逻辑放在代码组(?{})

mutilpe行的Mod
注意 - 如果需要重新校准(按3),请告诉我 到目前为止,对齐是3个非空白+可选的空格,重复 这将消耗换行符,同时保持3边界 - 我 假设很重要。

Perl代码

use strict;
use warnings;

my %AminoAcid   = (
   aug => "Start codon",
   ccc => "C",
   ggg => "G",
   uuu => "U"
);

my $RNA = '
aaaaugcccgggugacccgggcccgggcccaaaauguuugggcccugacccgggccccccaugccc
gggugacccgggcccgggcccaaaauguuugggcccugacccgggcccccc
aaaaugcccgggugacccgggcccgggcccaaaauguuugggcccugacccgggcccccc
aaaaugcccgggugacccgggcccgggcccaaaauguuugggcccugacccgggcccccc
';
my $on = 0;

$RNA =~ /
     (?:
          ( \S\S\S ) \s*
          (?{
               if ( $^N eq 'aug' ){ $on = 1; print "\n"; }
               elsif ( $^N eq 'uga' ) { $on = 0; }
               if ( $on ) {
                  exists $AminoAcid{ $^N } ?
                    print $AminoAcid{ $^N } :
                    print "[key not found-> '$^N']";
               }
          })
     )+
   /x;

输出

Start codonCG
Start codonUGC
Start codonCG
Start codonUGC
Start codonCG
Start codonUGC
Start codonCG
Start codonUGC

答案 2 :(得分:0)

@ lucas-trzesniewski的sub非常棒而且非常紧凑,但它有一些缺点:它不处理穿插的硬回车,只找到第一个蛋白质,不打印第一个蛋氨酸,并用一个修改$ _ / $ 1隐式返回(这是我试图避免的)。所以这是一个改进。请注意,我有一个非常精巧的翻译脚本,我自己处理了更多的案例(例如重叠的阅读框架,模糊的核苷酸,RNA片段,交替的起始密码子,多个终止密码子等),但如果你只是想要一些简单的东西对于有限的案例,这里是@ lucas-trzesniewski子的修改版本,解决了这些问题:

sub getAminoAcids
  {
    my $mrna = @_;
    $mrna =~ s/\s+//sg;
    $mrna = lc($mrna);
    my @proteins = ();
    while($mrna =~ /(aug(?:[acgu]{3})*?)uga/g)
      {
        $cds = $1;
        push(@proteins,"");
        while($cds =~ /(...)/g)
          {$proteins[-1] .= $aminoAcidMap{$1}}
      }
    return(@proteins);
  }

这假设您不想在蛋白质字符串中打印停止字符。它也可能有额外的错误检查。