Linux使用ragel进行文本快速解析(上)

1、前言

  在项目中我们经常涉及一些文本解析处理的场景,大部分场景是进行简单解析且数据量不大,但本文要讨论的是某些特定场景下,需要高性能解析大量文本的处理,如百万级每秒的日志解析。翻看Intel 的 hyperscan 依赖,发现有一款解析引擎Ragel,特性非常棒,可以拉出来进行实践。

  当我们对文本(协议)进行解析的时候,有许多工具、语言可以进行选择。需求考虑一种实用、高效的可编程语言,但又要避免乏味、语义晦涩的写法。在这些工具像Lex、Re2C,或者sed、awk、perl脚本中,我们会发现有一个共同点:他们都是使用正则表达式匹配引擎,结合特定的程序处理逻辑来实现的。

  经过大家的经验累积,我们得出一种结论:正则表达式可以清晰描述处理流程,而状态机可以可靠、快速地执行该流程。所以引入Ragel的编程哲学:开发者使用易理解的正则表达式来设计流程,然后生成高效的状态机代码给机器运行。

2、相关知识

  以下通过 Ragel 官方手册[^2] 我们进行一部分的翻译理解,来逐步掌握这个工具。

  Ragel 是一款代码生成器,他对常规的语言进行编译,生成有限状态机(FSM)代码。Ragel支持生成C、C++、ASM。Ragel 的状态机不仅可以使用正则表达式识别字节序列,而且可以在匹配过程中执行相关操作。Ragel生成相关的嵌入代码将使用内联操作,并不会破坏原语言的语法结构。

  Ragel的核心语言包括正则表达式运算符、动作(action)嵌入运算符。用户的正则表达式将被编译为确定的状态机,并且执行指定的动作。编程的核心在于理解正则表达式和确定性有限状态机的关系。

2.1、简介

2.1.1 Ragel 优势

  1. 实现健壮的协议;
  2. 解析数据格式;
  3. 编程语言的语法分析;
  4. 验证用户输入;

2.1.2 Ragel 特性

  1. 结合常规代码、状态图表、扫描器就能构建FSM;
  2. 支持在FSM任意位置插入执行的动作;
  3. 使用防御性操作控制流程不确定性;
  4. 使用Hopcroft算法实现最小自动机;
  5. 支持Graphviz软件对FSM可视化;
  6. 使用单字节、双字节、字长的字母表;
  7. 在非依赖情况下生成C、C++、ASM(GNU, x86_64, System V ABI) 代码;
  8. 可选使用表、控制流去驱动状态机;

2.2 状态机(mechine)概念

  Ragel 对于字符串的解析,是用一种结合正则表达式的机器语言来描述,可表现为内嵌的状态机语言规范。这种机器语言通过扫描输入的字符串,匹配状态机的特定状态进行处理,当扫描结束的时候,处理也随之完成。这种有限状态机语言可以由数行代码完成,使用标识符 %%{ 开始、使用 }%% 结束,也可以使用 %% 开始的一行进行实现。

  下面看一个简单例子,该例子判断输入字符串中是否含有’foo’或’bar’字符:

#include <string.h>
#include <stdio.h>
%%{
   
machine foo;
main :=
	( ’foo’ | ’bar’ )
	0 @{
    res = 1; };
}%%
%% write data;

int main( int argc, char **argv )
{
   
	int cs, res = 0;
	if ( argc > 1 ) {
   
		char *p = argv[1];
		char *pe = p + strlen(p) + 1;
		%% write init;
		%% write exec;
	}
	printf("result = %i\n", res );
	return 0;
}

Ragel语法的文件为rl后缀命名,内部expression支持正则表达式的语法:

命名:machine fsm_name;
定义: = ;
实例化: = ;
引用:include FsmName “inputfile.rl”;
引用:import “inputfile.h”;

2.3 动作(action)的概念

  Ragel 允许自定义动作嵌入到正则表达式对应的状态机动作之中,随着FSM的状态迁移,自定义动作随之执行。与正则表达式一样,action 动作操作符是可以任意组合的。由于动作可以嵌入组成,用户可以完全自由地定义动作。

action ActionName {
   
	/* Code an action here. */
    count += 1;
}

动作的触发是在配合 FSM 状态迁移进行,按照动作大类区分有:

>开始状态
< 除了开始状态的其他状态
$ 任意状态下
% 结束状态
@ 除了结束状态的任意状态
<> 中间状态(除了开始状态和结束状态)

按动作小类区分有:

~ (to)迁移其他状态时的动作
* (from) 从其他状态迁移过来时的动作
/ (eof)EOF时的动作
! (err)发生错误时的动作
^ (lerr)本地错误时的动作

下面列举一个例子来表示如何处理错误,在解析失败时时进行信息提示,并跳转到错误处理,当错误处理完成后

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值