Regex Perl仅替换树中的顶级数字

Regex Perl仅替换树中的顶级数字,regex,string,perl,bioinformatics,bioperl,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); 我已经尽了最大努力想出了一个合适的正则

我是这个网站的新手。这是一个困扰我超过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);

我已经尽了最大努力想出了一个合适的正则表达式,但最终承认了我的局限性。如何才能真正做到这一点呢?

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

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)";
使用严格;使用警告;使用特征qw(例如);
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+)(,|$)
(?(定义)
(?[(](?&ELEM)(?:,(?&ELEM))*[)]
((&预备课程):\d+)
(?(?:[A-Z]|(?&子列表)))
)
}{“$1:”($2+10)。$3}gex;
说“($string)”;
打印
((A:14,B:43):32,C:86,(D:54,(E:87,F:28):17):45)


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

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

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)";
使用严格;使用警告;使用特征qw(例如);
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+)(,|$)
(?(定义)
(?[(](?&ELEM)(?:,(?&ELEM))*[)]
((&预备课程):\d+)
(?(?:[A-Z]|(?&子列表)))
)
}{“$1:”($2+10)。$3}gex;
说“($string)”;
打印
((A:14,B:43):32,C:86,(D:54,(E:87,F:28):17):45)

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

匹配要跳过的内容或前面有一个数字:

您想跳过的内容要么是前导的
,要么是任何一组平衡的括号(平衡括号regex几乎是从字面上取的)

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

但是你最好不要太聪明,而是着手解析、修改和重新序列化你的树

匹配要跳过的内容或前面有一个数字:

您想跳过的内容要么是前导的
,要么是任何一组平衡的括号(平衡括号regex几乎是从字面上取的)

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


但最好不要太聪明,而是着手解析、修改和重新序列化树。

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

首先定义一个“键”,它可以是一串大写字母,也可以是括号中任意数量的键:值对

然后找到所有键,后跟一个冒号和一个十进制数,并对该数字进行算术运算

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;

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

首先定义一个“键”,它可以是一串大写字母,也可以是括号中任意数量的键:值对

然后找到所有键,后跟一个冒号和一个十进制数,并对该数字进行算术运算

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;
首先,我要感谢这篇帖子。从这篇帖子中,我学会了如何以及为什么应用
\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)
首先,我要感谢这篇帖子。从这篇帖子中,我学会了如何以及为什么应用
\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)

我只是简单地将字符串解析成一个实际的对象树层次结构,然后完成工作并将树序列化回字符串。我不知道这在您的情况下是否可行,但这似乎是一种合乎逻辑的方法。您考虑过吗?我相信它包括解析和操作树内容的工具。我对它了解不多,但是搜索结果显示,我已经猜到在那个横幅下存在类似的东西。也许吧。感谢大家推荐Bioperl。我把它安装在自己的工作站上。它确实有广泛的树功能。但对于这个特殊的东西,我只是想它可能在没有Bioperl的计算机上工作。例如,office Mac桌面。因此,没有特殊库的通用解决方案可能更好