基于POSIX下REGEX库的文本URL过滤(C/C++语言)
来源:互联网 发布:crf算法 编辑:程序博客网 时间:2024/06/14 02:17
URL过滤报告
URL过滤需求分析:
输入为带中文、英文、标点符号、特殊符号等的字符串,输出也是字符串,但有以下要求:
1.把输入字符串中的网站URL(以“http://”开头)、文件URL(以“.xxx(若干个x)结尾”)的子串找到,并删除。
2.将其他的无关字符串原样保留,去除需要过滤的URL之后,直接拼接。
3.输出去掉所有URL,其他保持不变的字符串。
URL过滤技术分析:
1.将用户需求转换为以下正则表达式:
"(http://[a-zA-Z0-9./?%&_=-]+)|([a-zA-Z0-9_-]+\\.[a-zA-Z0-9]+)"
该正则表达式表示的意思为:
a.以http://开头,接着跟1个或多个包含在集合{a-zA-Z0-9./?%&_=-}的字符。
b.前面包含1个或多个{a-zA-Z0-9_-}集合中的字符,然后跟一个点(根据语法,需要写成\\.),最后跟1个或多个{a-zA-Z0-9_-}集合中的字符。
2.使用POSIX标准的regex库,包含regex.h头文件。首先在初始化过程中,使用函数regcomp编译正则表达式。之后在匹配过程中,使用函数regexec执行匹配,如果匹配到,则将匹配到的字符串删除。多次匹配删除,直到整个字符串处理完毕。最后调用regfree释放内存资源。
URL过滤测试:
测试配置:网络名为LT_Kdc_DE的开发机,3G Mem,2G Swap内存,Intel(R) Xeon(R) CPU E5606 @ 2.13GHz单处理器,CentOS Linux release 6.2 (Final)操作系统。
测试样本为包含中文、英文、标点符号、特殊符号的一篇短文,共有26行,5742个字符,3个网站URL,1个文件URL。
对文本的每行依次输入(共输入26次),输出结果能够正确的去除掉里面的URL,同时不影响其他无关字符串。
对文本的每行依次输入,反复循环执行100,000次正则匹配,共执行2,600,000次匹配调用的压力测试。十次压力测试的执行时间如下(单位ms):
1842
1838
1880
1842
1848
1849
1902
1849
1856
1860
平均值为2,600,000次/1856.8ms,转换为1,400,256次/s≈140w/s。基本满足性能需求。
关于正则表达式:
URL过滤规则中比较关键的是如何构建你所希望的URL正则表达式,网上有很多关于正则表达式的相关文章。在书写正则表达式集合中有个很需要注意的事项,特殊字符需要注意位置,在[]中想把]^-当成普通字符,是有要求:
] 要放在第一个
^ 不能放在第一个
- 要放在第一个或者最后一个
扩展:
如果以后需要用到类似于URL过滤或文本过滤的模块,只需要修改正则表达式规则,及少许业务上的定制就行了。性能上,根据业务需求,优化一些字符串拷贝,删除以及内存分配的函数,可以进一步优化性能。如果追求更高的性能,可以采用自定义有限自动机的方式,根据业务来定制,但这样实现较为复杂,编程难度较大,并且容易出错。
源代码:
#include <sys/types.h>#include <sys/time.h>#include <regex.h>#include <string.h>#include <iostream>#include <fstream>#include <string>bool init(regex_t & reg){int status;int cflags = REG_EXTENDED; //支持正则表达式扩展标签// 过滤规则:以http://开头或以.xxx(若干个x)结尾的字符串const char * pattern = "(http://[a-zA-Z0-9./?%&_=-]+)|([a-zA-Z0-9_-]+\\.[a-zA-Z0-9]+)"; if((status = regcomp(®, pattern, cflags)) != 0)//编译正则表达式{std::cerr << "pattern compile error" << std::endl;char err_buff[1024];regerror(status, ®, err_buff, 1024);std::cout << "error message:" << err_buff << std::endl;return false;}return true;}bool destroy(regex_t & reg){regfree(®);}bool url_filter(regex_t & reg, std::string & input, std::string & output) {int status;regmatch_t pmatch[1];const size_t nmatch = 1;// regex函数必须匹配'\0'结尾的字符串input.append(1,'\0');char * st = new char[input.length()];input.copy(st, input.length(), 0);//循环匹配多次while( st && (status = regexec(®, st, nmatch, pmatch, REG_NOTEOL)) != REG_NOMATCH){int num = pmatch[0].rm_eo - pmatch[0].rm_so;//std::cout << "<" << input.substr(pmatch[0].rm_so, num) << ">" << std::endl;//删除匹配到的字符串input.erase(pmatch[0].rm_so, num);input.copy(st, input.length(), 0);}// 删除掉我们添加的'\0'output = input.erase(input.length() - 1, 1);return true;}// test int main(int argc, char *argv[]){std::string input, output;//input = "此电摩VID_20160531_194403.mp4 一出,http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%20%E5%AD%97%E7%AC%A6%20%26&rsv_pq=cd1686ec0020b7eb&rsv_t=21a17dKwt642CgDFL8JxM%2Ft1ywlP4OECwVMil5Ij%2FbCWJdOc6UXRr%2BMaDr4&rqlang=cn&rsv_enter=1&rsv_sug3=27&rsv_sug1=20&rsv_sug7=101&rsv_sug2=0&inputT=7511&rsv_sug4=7997 谁还要汽车 http://www.arxql.zx58.cn/wanghao/1.html 玩微信的朋友可以加我微信gxys6666[em]e400905[/em]小号点这里[em]e400389[/em]二维码页面,post:_wv 1 srctype touch apptype iphone loginuin 120340009 plateform mobileqq url http%253A%252F%252Fqm.qq.com%252Fcgi-bin%252Fqm%252Fqr%253Fk%253D3t-ZOf2mUGLPAheKhi2l_c5KmisysqWH src_uin 120340009 src_scene 311 cli_scene getDetailzuzu气垫BB,只涂了半边脸,提亮肤色,特别保湿,遮盖力超级好,不挂粉,一整天都不脱妆 快来围观我的精彩微视频! http://xiaoying.tv/v/e3qd9/2/?fromApp XiaoYing toApp qzone(通过#小影#创作)";//std::cout << input << std::endl << std::endl;int test_times = 100000;//压力测试次数struct timeval ts, te;//开始时间和结束时间if(argc != 2){std::cout << "usage: ./a.out input_file" << std::endl;return 1;}std::fstream in(argv[1]);regex_t reg;if(!init(reg)){std::cerr << "init reg error" << std::endl;return 1;}gettimeofday(&ts, NULL);while(getline(in, input)){for(int i = 0; i < test_times; i++){url_filter(reg, input, output);}}gettimeofday(&te, NULL);destroy(reg);std::cout << "total time used : " << (1000000 * (te.tv_sec - ts.tv_sec) + te.tv_usec - ts.tv_usec)/1000 << " ms" << std::endl;std::cout << "total test_times : " << test_times << std::endl;//std::cout << output << std::endl << std::endl;return 0;}
- 基于POSIX下REGEX库的文本URL过滤(C/C++语言)
- C语言的正则表达式 regex
- C语言正则表达式库RegEx库
- 线程概述——基于POSIX的C语言多线程基础知识(一)
- 【C语言】实现一个基于命令行的文本编辑器
- C语言正则表达式regex
- “基于关键字匹配的文本过滤系统”配置文件的设计和实现(C/C++源码)
- C语言实现dos界面下的文本颜色变色
- C编写的跨平台线程池 - 基于POSIX threads
- C++regex
- linux下c语言url请求
- Linux下C语言url请求
- 基于POSIX在Linux下C语言实现读取整个目录文件[Get a List of Files in a Directory with C]
- 关于boost.regex库的编译问题(C/C++)
- c语言中的正则表达式regex.h
- c语言中的正则表达式regex.h
- windows下C/C++的正则表达式库之GNU Regex Library
- 基于C语言的windows下的web服务器
- 学生信息管理系统调错总结一 (你不该犯的那些错)
- n个骰子的点数44
- nigix配置成功,但是不能访问
- Android webview,js,属性
- Mac版MySQL修改初始密码
- 基于POSIX下REGEX库的文本URL过滤(C/C++语言)
- Intel CPU 地址空间总结
- 读《灵魂只能独行》乱摘
- 演讲稿
- linux中ssh使用rsa免密码登录方法
- python开发环境搭建 (eclipse)
- vim常用命令总结
- MySQ的列类型的选择原则
- 获取偶数位和奇数位并输出二进制序列,采用右移符>>。