如何从perl中的正则表达式中排除特定模式?

时间:2012-11-29 11:11:29

标签: regex perl

我对正则表达式有点麻烦。我有以下一个:(A|C|G|T){3},其中包含来自A,B,C,D的三个字母的每个排列,但现在我想排除三个特定模式:"TAG""TAA"和{{ 1}}。尝试"TGA",但它没有产生预期的结果。使用look-around(向前看并向后看)也是如此。

我想要实现的是找到以“ATG”开头的所有子字符串,以“TAG”,“TAA”或“TGA”结尾,在中间它应该有A,C的三元组, G或T.

感谢您的帮助!

这是我到目前为止所做的:

[^]

2 个答案:

答案 0 :(得分:5)

如果我理解正确:

1)从ATG开始

2)许多三胞胎,除了'TAG','TAA'和'TGA'

3)其中一个三胞胎'TAG','TAA'或'TGA'

这应该有效:

/
   (ATG)                       # Step 1
   ((?!TAG|TAA|TGA)[ACGT]{3})+ # Step 2
   (TAG|TAA|TGA)               # Step 3
/x

与你的区别在于,第二个想法是在量词中移动负面预测以获得“多个三元组”步骤,确保三个三元组都不是例外之一

此解决方案不假设步骤2和步骤3中的元素之间存在任何共性。更简单但在您的情况下等效的配方将是:

1)匹配'ATG'

2)匹配多个三元组

3)...直到你匹配'TAG','TAA','TGA'。

要做到这一点,你只需要让步骤2中的量词非贪婪,因为如果步骤2再次匹配,这将测试第3步匹配。

然后解决方案看起来像:

/ (ATG) ([ACGT]{3})*? (TAG|TAA|TGA) /x

另一种解释可能是:

1)从ATG开始

2)许多三胞胎

3)其中一个三胞胎'TAG','TAA','TGA'

4)步骤2中找到的子字符串不得包含子字符串'TAG','TAA','TGA'。

在这种情况下,我会使用两个正则表达式来解决它。实施步骤1-3和步骤4中的测试:

 $sequence =~ /(ATG)([ACGT]{3})(TAG|TAA|TGA)/ and $2 !~ /TAG|TAA|TGA/;

答案 1 :(得分:0)

在您的情况下,您不必排除中间的任何内容 - 假设您希望最长的序列匹配。这就是Perl的*+已经做到的事情:他们贪婪并且匹配最长的序列。

因此,在一个简化的示例中,如果您的输入为ABAACAAC,并且您希望将以B开头的所有内容与C的所有内容匹配,AB }或C在中间,m/A[ABC]*C/已匹配BAACAAC,而不只是BAAC

一般来说,你不能使用正则表达式来排除中间的特定事物(尽管有零宽度负前瞻/后视断言等事情)。

编辑:如果你想在第一次出现“结束模式”时停止匹配,那么只需通过*后缀来使?非贪婪。我的非贪婪的例子:m/A[ABC]*?C/,虽然在这种情况下我也可以省略char类中的C(因为在这个简化的例子中它只是一个字母)。