如何阅读perl正则表达式调试器

时间:2015-03-20 13:17:28

标签: regex perl debugging

我遇到过以下材料:

  1. Mastering Perl brian d foy,章节:调试正则表达式。
  2. Debugging regular expressions提及re::debug模块for perl
  3. 我也尝试使用其他各种技术:

    1. Module re=debugcolor突出了它的输出。

    2. Used在构建?{print "$1 $2\n"}之后。

    3. 但仍然没有明白如何阅读他们的输出。我还发现了另一个用于调试正则表达式here的模块但是我还没有尝试过它们,请你解释一下如何读取use re 'debug'的输出或者用于调试正则表达式的其他命令Perl的?

      编辑回复鲍罗丁:

      第一个例子:

      perl -Mre=debug -e' "foobar"=~/(.)\1/'
      Compiling REx "(.)\1"
      Final program:
         1: OPEN1 (3)
         3:   REG_ANY (4)
         4: CLOSE1 (6)
         6: REF1 (8)
         8: END (0)
      minlen 1
      Matching REx "(.)\1" against "foobar"
         0 <> <foobar>             |  1:OPEN1(3)
         0 <> <foobar>             |  3:REG_ANY(4)
         1 <f> <oobar>             |  4:CLOSE1(6)
         1 <f> <oobar>             |  6:REF1(8)
                                        failed...
         1 <f> <oobar>             |  1:OPEN1(3)
         1 <f> <oobar>             |  3:REG_ANY(4)
         2 <fo> <obar>             |  4:CLOSE1(6)
         2 <fo> <obar>             |  6:REF1(8)
         3 <foo> <bar>             |  8:END(0)
      Match successful!
      Freeing REx: "(.)\1"
      
      1. OPEN1,REG_ANY,CLOSE1 ......是什么意思?
      2. 像1 3 4 6 8这样的数字是什么意思?
      3. 大括号OPEN1(3)中的数字是什么意思?
      4. 我应该查看哪个输出,编译REx或匹配REx?
      5. 第二个例子:

         perl -Mre=debugcolor -e' "foobar"=~/(.*)\1/'
        Compiling REx "(.*)\1"
        Final program:
           1: OPEN1 (3)
           3:   STAR (5)
           4:     REG_ANY (0)
           5: CLOSE1 (7)
           7: REF1 (9)
           9: END (0)
        minlen 0
        Matching REx "(.*)\1" against "foobar"
           0 <foobar>|  1:OPEN1(3)
           0 <foobar>|  3:STAR(5)
                                          REG_ANY can match 6 times out of 2147483647...
           6 <foobar>|  5:  CLOSE1(7)
           6 <foobar>|  7:  REF1(9)
                                            failed...
           5 <foobar>|  5:  CLOSE1(7)
           5 <foobar>|  7:  REF1(9)
                                            failed...
           4 <foobar>|  5:  CLOSE1(7)
           4 <foobar>|  7:  REF1(9)
                                            failed...
           3 <foobar>|  5:  CLOSE1(7)
           3 <foobar>|  7:  REF1(9)
                                            failed...
           2 <foobar>|  5:  CLOSE1(7)
           2 <foobar>|  7:  REF1(9)
                                            failed...
           1 <foobar>|  5:  CLOSE1(7)
           1 <foobar>|  7:  REF1(9)
                                            failed...
           0 <foobar>|  5:  CLOSE1(7)
           0 <foobar>|  7:  REF1(9)
           0 <foobar>|  9:  END(0)
        Match successful!
        Freeing REx: "(.*)\1"
        
        1. 为什么数字在这个例子中下降6 5 4 3?
        2. 失败的关键字是什么意思?

2 个答案:

答案 0 :(得分:4)

正则表达式定义有限状态机 1 。调试器或多或少地向您显示状态机的进展情况,因为字符串是按字符消耗的。

&#34;编译REx&#34;是该正则表达式的说明列表。每个指令后括号中的数字是步骤成功后的位置。在/(.*)\1/

1: OPEN1 (3)
3:   STAR (5)
4:     REG_ANY (0)
5: CLOSE1 (7)

STAR (5)表示计算STAR,一旦成功,请转到指令5 CLOSE1

&#34;匹配REx&#34;是逐步执行这些指令。左边的数字是到目前为止消耗的字符总数。如果匹配器必须倒退,这个数字可能会下降,因为它尝试的东西都不起作用。

要理解这些说明,了解正则表达式如何工作非常重要。&#34;有限状态机通常可视化为一种流程图。我在/(.)\1/下面制作了一个粗略的。由于对捕获组的反向引用,我不相信这个正则表达式是一个严格的有限状态机。该图表也很有用。

               Match                           
+-------+     Anything     +----------+        
| Start +------------------+  State 1 |        
+---^---+                  +--+---+---+        
    |                         |   |            
    |                         |   |Matched same
    +-------------------------+   | character  
            matched different     |            
                character    +----+------+     
                             |  Success  |     
                             +-----------+   

我们从Start开始。它很容易进入第一个状态,我们只消耗任何一个字符(REG_ANY)。唯一可能发生的事情是输入结束。我还没有在这里画出来。 REG_ANY指令包含在捕获组指令中。 OPEN1开始将所有匹配的字符记录到第一个捕获组中。 CLOSE1停止将字符记录到第一个捕获组。

一旦我们消费了一个角色,我们就坐在State 1上并消耗下一个角色。如果它与之前的字符匹配,我们就会成功! REF1是尝试匹配捕获组#1的指令。否则,我们失败了,需要回到Start再试一次。只要匹配者说'#34;失败......&#34;它告诉你某些东西不起作用,所以它回到了一个早期的状态(可能包括也可能不包括“没有消耗的人物”)。

*的示例更复杂。 *(对应于STAR)尝试将给定模式匹配零次或多次,并且 greedy 。这意味着它尝试匹配尽可能多的字符。从字符串的开头开始,它表示&#34;我最多可以匹配6个字符!&#34;因此,它匹配所有6个字符("foobar"),关闭捕获组,并尝试再次匹配"foobar"。这不起作用!它再次尝试5,这不起作用。依此类推,直到它尝试匹配零个字符。这意味着捕获组为空,匹配空字符串总是成功。所以匹配成功\1 = ""

我意识到我花了更多的时间来解释正则表达式,而不是使用Perl的正则表达式调试器。但是,一旦你理解了正则表达式如何运作,我认为它的输出会变得更加清晰。

这是finite state machine simulator。您可以输入正则表达式并查看它是否已执行。不幸的是,它不支持反向引用。

1:我相信Perl的一些正则表达式功能超越了这个定义,但以这种方式思考它们仍然很有用。

答案 1 :(得分:2)

调试信息包含字节码的描述。数字表示操作树中的节点索引。圆括号中的数字表示引擎在匹配时跳转到特定节点。 EXACT运算符告诉正则表达式引擎查找文字字符串。 REG_ANY表示。符号。 PLUS表示+。代码0用于'结束'节点。 OPEN1是'('符号.CLOSE1表示')'。 STAR是'*'。当匹配器到达结束节点时,它会将成功代码返回给Perl,表明整个正则表达式已匹配。

http://perldoc.perl.org/perldebguts.html#Debugging-Regular-Expressions和更具概念性的http://perl.plover.com/Rx/paper/

上查看更多详情