模式匹配的搜索流程是什么?

时间:2015-10-03 06:36:04

标签: regex string perl

我的字符串是

$s = "AAATAATAGCAV";

模式1

$s =~m/AT?.?A/g; 

此处T?无法搜索。 .?匹配字符串第二个字符(A A A),最后A匹配(AA A

模式2

$s =~m/A.?T?A/g

.?匹配第二个字符。 T?无法搜索。结果相同

这是我的疑问

$s =~m/A.?T?AA/

从头开始A匹配字符串

中的第一个字符

.?匹配任何一个字符匹配或不匹配字符串。所以它匹配第二个字符作为模式1和模式2.

T?也匹配任何一个字符匹配或不匹配字符串。

AA匹配字符串中的AA字符。

为什么以上模式不会与AATAAATAA匹配。搜索引擎如何运作。为什么结果为AAA

3 个答案:

答案 0 :(得分:2)

有一种很简单的方法可以看出正则表达式在做什么:

 use re 'debug';

E.g:

#!/usr/bin/env perl 
use strict;
use warnings;

use re 'debug';

my $str = 'AAATAATAGCAV';    
$str =~m/A.?T?AA/;

这将打印:

Compiling REx "A.?T?AA"
Final program:
   1: EXACT <A> (3)
   3: CURLY {0,1} (6)
   5:   REG_ANY (0)
   6: CURLY {0,1} (10)
   8:   EXACT <T> (0)
  10: EXACT <AA> (12)
  12: END (0)
anchored "A" at 0 floating "AA" at 1..3 (checking floating) minlen 3 
Matching REx "A.?T?AA" against "AAATAATAGCAV"
Intuit: trying to determine minimum start position...
  doing 'check' fbm scan, [1..12] gave 1
  Found floating substr "AA" at offset 1 (rx_origin now 0)...
  doing 'other' fbm scan, [0..1] gave 0
  Found anchored substr "A" at offset 0 (rx_origin now 0)...
  (multiline anchor test skipped)
Intuit: Successfully guessed: match at offset 0
   0 <> <AAATAATAGC>         |  1:EXACT <A>(3)
   1 <A> <AATAATAGCA>        |  3:CURLY {0,1}(6)
                                  REG_ANY can match 1 times out of 1...
   2 <AA> <ATAATAGCAV>       |  6:  CURLY {0,1}(10)
                                    EXACT <T> can match 0 times out of 1...
   2 <AA> <ATAATAGCAV>       | 10:    EXACT <AA>(12)
                                      failed...
                                    failed...
   1 <A> <AATAATAGCA>        |  6:  CURLY {0,1}(10)
                                    EXACT <T> can match 0 times out of 1...
   1 <A> <AATAATAGCA>        | 10:    EXACT <AA>(12)
   3 <AAA> <TAATAGCAV>       | 12:    END(0)
Match successful!
Freeing REx: "A.?T?AA"

所以回答你的问题 - 这在开始时与AAA匹配 - 因为你有一个可选的(.?),这意味着零有效。还有一个可选的T?,这意味着没有一个在那里也是有效的。

因此,第一个子字符串与您的目标模式匹配。通过这样做(默认情况下!)消耗该模式的一部分,使其无法再与之匹配。所以拿你的第一个例子:

#!/usr/bin/env perl 
use strict;
use warnings;
use Data::Dumper;

use re 'debug';

my $s = 'AAATAATAGCAV';
my @matches = $s =~m/(AT?.?A)/g; 
print Dumper \@matches; 

给出:

$VAR1 = [
          'AAA',
          'AA'
        ];

这会将第一个匹配项设为AAA,将第二个匹配项设置为字符串AA(AAA)T(AA)TAGCAV。由于子字符串已匹配,因此模式匹配引擎不再“可用”。如果你真的需要,你可以做到这一点,但是如果你要走下去,我建议你努力思考你正在尝试用你的正则表达式做什么。但您可以使用"look around"匹配。

另外:通常使用单个char变量名称的形式非常糟糕。称之为描述性的东西。

答案 1 :(得分:2)

我在正则表达式中添加了一个嵌入代码,以查看引擎在搜索时的位置。这里的关键是理解“碰撞”。

匹配完成后,下一场可能的匹配只能在上一场比赛结束后开始。

在打印进度时运行

my $s = "AAATAATAGCAV";
my $n = 1;

while($s =~  
    m/

      # Embedded code construct (?{ })
      (?{print "\n", $n++, ". Starting match at: [$`||$']: "})  

      # Same as AT?.?A
      A T? .? A                                

   /gx  

){
   print "Found: [$&]";
}

带符号||的输出表示当前的位置:

1. Starting match at: [||AAATAATAGCAV]: Found: [AAA]
2. Starting match at: [AAAT||AATAGCAV]: Found: [AA]
3. Starting match at: [AAATAAT||AGCAV]: 
4. Starting match at: [AAATAATAGC||AV]: 

详细说明步骤:

  1. 在以下地点开始比赛:[|| AAATAATAGCAV]:发现:[AAA]

    • A:从头开始。
    • B:找到'A'(通过)。
    • C:'T?'可选'T'(所以仍然是通行证)。
    • D:'。?'任何可选字符(匹配字符串中的第二个'A')(发现它仍然是一个通行证)
    • E:找到'A'(通过)。
  2. 以上是上述步骤的进展情况:

    • A:字符串:|| AAATAATAGCAV。正则表达式:|| AT?。?A
    • B:字符串:| A | AATAATAGCAV。正则表达式:| A | T?。?A
    • C:String:| A | AATAATAGCAV。正则表达式:| AT?|。?A
    • D:字符串:| AA | ATAATAGCAV。正则表达式:| AT?。?| A
    • E:String:| AAA | TAATAGCAV。正则表达式:| AT?。?A |

    2把钥匙

    1. 由于我们包含了\ g修饰符,因此正则表达式希望找到其他匹配项。
    2. 由于我们已找到匹配项,因此下一次可能的匹配必须在最后一场比赛结束后开始。在这种情况下,正则表达式找到'AAA'。下一场比赛只能从这里开始:AAAT ** || ** AATAGCAV

答案 2 :(得分:1)

Regex: A.?T?AA
Text:  AAATAATAGCAV

正则表达式将从文本中的第一个字符开始匹配,并查看是否有任何方式匹配该模式。此外,?是贪婪的,所以它首先尝试匹配1个字符,如果失败,它将匹配0个字符。让我们看看这是如何转化为比赛的每一步:

Pattern: A.TAA
Text:    AAATAATAGCAV
           | Failed

The pattern failed while matching 'T' from 'T?', so now try to match 0 characters there.
Pattern: A.AA
Text:    AAATAATAGCAV
            | Failed

The pattern failed while matching the last 'A'. There's one more pattern now before moving on to the next character - the one where .? matches 0 characters.
Pattern: AAA
Text:    AAATAATAGCAV
         Success!