举个栗子

马辰龙De技术分享
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

正则匹配嵌套结构

Posted on 2016-07-11 11:15  ChenlongMa  阅读(6226)  评论(0编辑  收藏  举报

有以下文本

aaa  
bbb  
#if defined(__MMI_DEL__)  
   ccc  
#endif  
ddd  
eee  
#if defined(__MMI_DEL__)  
   fff  
   ggg  
#endif  
hhh 
要求匹配
注释外的内容,匹配之后的内容:
aaa
bbb
ddd
eee
hhh
可以利用/^xxx/../^xxx/结构来匹配 ,但是出现了以下的嵌套结构:
aaa  
bbb  
#if defined(__MMI_DEL__)  
   ccc  
#endif  
ddd  
eee  
#if defined(__MMI_DEL__)  
   fff  
   ggg  
#if defined(__EX222__)  
   KKK  
#if defined(__EX222__)  
woshi  
#endif  
  LLLL  
#endif  
#endif  
sdffff  
#if defined(__EX222__)  
sdfsdf  
sdff  
#endif  
sdfdsf 
就没法用用上面的结构了,必须要使用平衡组,或者是递归来做,其实上面的代码也可以看做是<div></div>
这种类型,简单点就是(1*(1+2)/3)这种类型的括号嵌套,可以利用(?R)来递归(perlre中有详解),或者是(??{code})
动态正则表达式结构。
以下我利用(??{code})来示范写了一段。。
#!/usr/bin/perl  
use strict;
use warnings;
my ( @arr, $re, $line, @tmp );
while (<DATA>) {
    chomp;
    s/#if\s*defined.*?$/(/g;    #这里替换成(和)方便匹配
    s/#endif/)/g;
    push @arr, $_;
}
$line .= "$_\_" for @arr;

#print $line;
$re = qr/(?>[^()]+|\((??{$re})\))*/;
while ( $line =~ /(\w*)\($re\)(\w+)/g ) {
    push @tmp, split /\_/, "$1$2";
}
print join( "\n", @tmp );
__DATA__  
aaa  
bbb  
#if defined(__MMI_DEL__)  
   ccc  
#endif  
ddd  
eee  
#if defined(__MMI_DEL__)  
   fff  
   ggg  
#if defined(__EX222__)  
   KKK  
#if defined(__EX222__)  
woshi  
#endif  
  LLLL  
#endif  
#endif  
sdffff  
#if defined(__EX222__)  
sdfsdf  
sdff  
#endif  
sdfdsf 

 output:

aaa
bbb

 
ddd
eee

 
sdffff

 
sdfdsf