Chinaunix首页 | 论坛 | 博客
  • 博客访问: 535055
  • 博文数量: 121
  • 博客积分: 4034
  • 博客等级: 上校
  • 技术积分: 1439
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-28 12:42
文章分类

全部博文(121)

文章存档

2017年(8)

2016年(10)

2013年(2)

2012年(3)

2011年(18)

2010年(80)

分类: C/C++

2010-11-26 19:32:35

使用正则表达式提取struct结构及内容


内容简介:演示如何在.Net环境下使用正则表达式将C代码头文件中struct结构及内容提取出来。
使用工具:RegexTester V1.1.1,Developed by IT民工。
          下载地址:右键点击另存为
          RegexTester是我使用VB.Net开发的正则表达式工具。关于它的使用,我会在另一篇文章中讲解。
测试平台:.Net Framework 1.0
任务描述:C语言头文件header.h,里面使用typedef struct格式定义了若干的结构。
          现在需要将每个结构提取出来,并提取出每个结构里面的每一个成员变量。
任务意义:完成这些提取,可以方便其他跨语言的工作。
          如将其存储为XML格式,或直接存入数据库,也可以从数据库中读取结构,构造树状视图等等。
关键字:  Regular Expression .Net typedef struct

文件header.h内容如下:
/*这只是一个例子,目的是演示
  如何使用正则表达式将C代码头文件中struct结构及内容提取出来*/
typedef struct st_Shit1
{
    u8  a;  //u8  = unsigned char
    u16 b;  //u16 = unsigned short
}t_Shit1;

/*这些注释都将被删除掉*/
typedef struct st_Shit2
{
    u8 c;
    PACK_U8                 //宏,u8的填充byte
    t_Shit1 a_Shit1[16];    //数组
}t_Shit2;

说明:u8是预定义的宏,代表unsigned char,u16也是预定义的宏,代表unsigned short。PACK_U8也是宏,展开后是一个Byte的填充。

步骤如下:
1、删除/* ... */的多行注释
2、删除//的单行注释
3、从无注释代码中分解出每一个struct的名称和内容
4、从每一个struct的内容中分解出每个成员变量的名称和类型

详述如下:
1、删除/* ... */的多行注释
匹配式为:/\*.*?\*/
替换式为:(空)
正则选项:SingleLine
替换之后结果为:

typedef struct st_Shit1
{
    u8  a;  //u8  = unsigned char
    u16 b;  //u16 = unsigned short
}t_Shit1;


typedef struct st_Shit2
{
    u8 c;
    PACK_U8                 //宏,u8的填充byte
    t_Shit1 a_Shit1[16];    //数组
}t_Shit2;

可以看到/* ... */的注释被删除了。

2、删除//的单行注释
匹配式为://[^\r\n]*
替换式为:(空)
正则选项:默认
替换之后结果为:

typedef struct st_Shit1
{
    u8  a;  
    u16 b;  
}t_Shit1;


typedef struct st_Shit2
{
    u8 c;
    PACK_U8                 
    t_Shit1 a_Shit1[16];    
}t_Shit2;

可以看到//...的注释被删除了。

3、从无注释代码中分解出每一个struct的名称和内容
匹配式为:typedef\s+struct\s+(?\w+)\s*\{\s*(?[\w\;\s\[\]\{\}]+?)\s*}(?\w+)\s*\;
替换式为:Type = ${st_},Name = ${st_},Content = ${content}
正则选项:默认
替换之后结果为:

Type = st_Shit1,Name = st_Shit1,Content = u8  a;  
    u16 b;


Type = st_Shit2,Name = st_Shit2,Content = u8 c;
    PACK_U8                 
    t_Shit1 a_Shit1[16];

可以看到struct的名称和内容都被分解出来了。

4、从每一个struct的内容中分解出每个成员变量的名称和类型
匹配式为:\s*(?\w+)\s*((?\w+)\s*(\[(?\w+)\s*\])?\s*\;)?
替换式为:Type:${Type}, Name:${Name}, Len:${Length}
正则选项:默认

对第1个struct的内容进行处理,输入:
 u8  a;  
    u16 b;
替换之后结果为:
Type:u8, Name:a, Len:
Type:u16, Name:b, Len:

对第2个struct的内容进行处理,输入:
 u8 c;
    PACK_U8                 
    t_Shit1 a_Shit1[16];
替换之后结果为:
Type:u8, Name:c, Len:
Type:PACK_U8, Name:, Len:
Type:t_Shit1, Name:a_Shit1, Len:16

可以看到struct内的成员变量的名称和类型,甚至数组的容量都被分解出来了。

注意事项:
1、这里举例使用的struct都是使用typedef struct定义的格式,如果是其他格式,就需要手工修改匹配的表达式了。
   也许会累一些,因为需要不断的测试。但是和其他麻烦的方法相比,正则表达式还是轻松多了:)
2、这里使用的是VB.Net的语法,其他的语言,构造基本相同,可能会有细节部分需要自行修改。
3、关于RegexTester这个工具,是我自己为了辅助工作需要而开发的,当然,网上也有不少类似的NB工具,可以自己搜索下载使用。
4、分解出来这些内容干什么用?当然不仅仅是为了好玩!我需要把它的结构保存起来......具体使用XML还是数据库还正在伤脑筋之中。
   好像XPATH 2.0的规范里面能够使用类似于SQL的语句,还不是很清楚,也许是个不错的选择......但是我还是倾向于使用数据库。
5、不熟悉正则表达式的同学,还是好好学习一下正则表示式吧,上面的那些式子中,用到了"非贪婪匹配","分组匹配"等知识......呵呵,其实都挺土的......

阅读(2615) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~