Perl仅替换树中的顶级数字

时间:2012-07-31 13:47:40

标签: regex string perl bioinformatics bioperl

我是这个网站的新手。这是一个困扰我> 2小时的问题。我有一个字符串(newick格式的系统发育树),看起来像:

((A:14,B:43):22,C:76,(D:54,(E:87,F:28):17):35);

树可能有多个级别,用括号表示。现在我想在顶级数字(分支长度)中添加一个数字,比方说10。这里只有三个顶级数字:22,76,35。转换后,字符串应如下所示:

((A:14,B:43):32,C:86,(D:54,(E:87,F:28):17):45);

我已经尽力了解正确的正则表达式,但终于承认了我的限制。怎么能真的做到?

4 个答案:

答案 0 :(得分:1)

虽然我会选择解析整个树,但只使用正则表达式可以解决问题:

use strict; use warnings; use feature qw(say);
my $string = "((A:14,B:43):22,C:76,(D:54,(E:87,F:28):17):35)";
$string =~ s/^\(//;
$string =~ s/\)$//;
$string =~ s{
    \G ((?&PRELEM)) : (\d+) (,|$)
    (?(DEFINE)
        (?<SUBLIST> [(] (?&ELEM)(?:,(?&ELEM))* [)] )
        (?<ELEM> (?&PRELEM) : \d+ )
        (?<PRELEM> (?:[A-Z]|(?&SUBLIST)) )
    )
 }{"$1:".($2+10).$3}gex;
 say "($string)";

打印((A:14,B:43):32,C:86,(D:54,(E:87,F:28):17):45)

我为自上而下的递归解析定义了一个小语法,请根据需要进行调整。在顶层,我们有无趣的Pre-Elements,我们存储在$1它们可以是一个单个字母或括在括号中的树。在:到达我们想要增加的数字后,存储在$2中。接下来是字符串或逗号的结尾。我们迭代匹配,从最后一个匹配的位置开始(由/g选项和\G断言表示)。当我们构建替换字符串时,会发生添加(我们正在使用/e选项)。

答案 1 :(得分:1)

s/(?:^\(|(\((?:(?>[^()]*)|(?1))*\)))\K|:\K([0-9]+)/$2?$2+10:""/ge

匹配要跳过的内容或前面带有数字的数字:。

您要跳过的内容可以是前导(或任何平衡的括号(平衡括号正则表达式几乎完全取自perlre)。

在替换中,如果要修改的数字匹配则添加10,否则不匹配。

但是你最好不要聪明,而是去工作来解析,修改和重新序列化你的树。

答案 2 :(得分:1)

这需要一个递归的正则表达式来匹配嵌套的括号。

首先定义一个'key',它是一串大写字母或括号之间的任意数量的key:value对。

然后找到所有键后跟冒号和十进制数字,然后对数字进行arithemtic。

use strict;
use warnings;

my $str = '((A:14,B:43):22,C:76,(D:54,(E:87,F:28):17):35)';

my $key = qr/ (?<key> [A-Z]+ | \( (?&key) : \d+ (?: , (?&key) : \d+ )* \)  ) /x;

$str =~ s/$key : \K ( \d+ ) /$2 + 10/xge;

print $str;

<强>输出

((A:14,B:43):32,C:86,(D:54,(E:87,F:28):17):45)

答案 3 :(得分:0)

首先,我要感谢此帖子中的ysth for his very interesting posting。从这篇文章中,我了解了如何以及为何应用\K eep修饰符。

我添加了另一个\K(到第一个子表达式)并对原子组使用了新的++表示法:

my $r = qr{
  (?:
     (?: ^ \(\K )
     |
     (
       \( (?: [^()]++ | (?1) )* \)
     )\K
  )
  |
  :\K (\d+)
}x;

输出字符串现在与输入字符串完全匹配 - 除了递增的值:

$t =~ s/$r/$2?$2+10:''/ge;

input:  ((A:14,B:43):22,C:76,(D:54,(E:87,F:28):17):35)
output: ((A:14,B:43):32,C:86,(D:54,(E:87,F:28):17):45)