天天看点

【Regular正则表达式】基础小练习(一)

目录

      • 01.引言
      • 02.正则的引擎分类介绍
          • 2.1 DFA引擎
          • 2.2 传统型NFA
          • 2.3 POSIX NFA
      • 03.正则的第三方库
      • 04.正则的简单运用
          • 4.1母串是否匹配
          • 4.2子串是否匹配(Working Example)
          • 4.3查找内容并替换
      • 05.正则求一些常用的字符串
          • 5.1 点分十进制
          • 5.2 网址(www.baidu.com等)
      • 06.正则小练习一总结

01.引言

今天我们就继上一篇正则的基本功进行下一步学习,分为正则的一些细分介绍和在C++中使用正则表达式来完成一些小操作,处理一些常用的字符串。

如果,这篇有些内容大家不懂,可以参考我的上一篇博客:【Regular正则表达式】正则表达式学习

02.正则的引擎分类介绍

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

正则引擎主要可以分为两大类:一种是DFA,一种是NFA。

主流的正则引擎又分为3类:1. DFA引擎 2. 传统型NFA 3. POSIX NFA

大概介绍 一下主流引擎:

2.1 DFA引擎

DFA 引擎在线性时状态下执行,因为它们不要求回溯(并因此它们永远不测试相同的字符两次)。DFA 引擎还可以确保匹配最长的可能的字符串。但是,因为 DFA 引擎只包含有限的状态,所以它不能匹配具有反向引用的模式;并且因为它不构造显示扩展,所以它不可以捕获子表达式。

使用DFA引擎的程序主要有:awk、egrep、flex、lex、MySQL、Procmail等。

2.2 传统型NFA

传统的 NFA 引擎运行所谓的“贪婪的”匹配回溯算法,以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。因为传统的 NFA 构造正则表达式的特定扩展以获得成功的匹配,所以它可以捕获子表达式匹配和匹配的反向引用。但是,因为传统的 NFA 回溯,所以它可以访问完全相同的状态多次(如果通过不同的路径到达该状态)。因此,在最坏情况下,它的执行速度可能非常慢。因为传统的 NFA 接受它找到的第一个匹配,所以它还可能会导致其他(可能更长)匹配未被发现。

使用传统型NFA引擎的程序主要有:GNUEmacs,Java,ergp,less,more,.NET语言,PCRE library,Perl,PHP,Python,Ruby,sed,vi等。

2.3 POSIX NFA

POSIX NFA 引擎与传统的 NFA 引擎类似,不同的一点在于:在它们可以确保已找到了可能的最长的匹配之前,它们将继续回溯。因此,POSIX NFA 引擎的速度慢于传统的 NFA 引擎;并且在使用 POSIX NFA 时,您恐怕不会愿意在更改回溯搜索的顺序的情况下来支持较短的匹配搜索,而非较长的匹配搜索。

使用POSIX NFA引擎的程序主要有:mawk,MorticeKern Systems’ utilities,GNU Emacs(使用时可以明确指定)。

注:也有使用DFA/NFA混合的引擎:GNUawk,GNU grep/egrep,Tcl。

03.正则的第三方库

这里提供三个版本的第三方库,仅供大家参考,有些语言是由封装的,不需要自己添加。

但是你要是想用当前语言没有的库,就只能手动配置一下第三方库,配置库的方法,网上一大堆,我就不举例了。

  1. PCRE库
    PCRE (PerlCompatible Regular Expressions) 包括 perl 兼容的正规表达式库.
    这些在执行正规表达式模式匹配时用与Perl 5同样的语法和语义是很有用的。 
    官方网站:
    		http://www.pcre.org/      
    		http://www.psyon.org/projects/pcre-win32/index.php(Win32版本)
               
  2. RE2库
    RE2是一个快速、安全和线程友好的C++正则表达式引擎。它使用DFA(有限状态机)引擎来
    对模式匹配进行加速。RE2库的语法参考附录1。 
    开源网站:
    		http://code.google.com/p/re2/wiki/Syntax(正则表达式语法)     
    		http://swtch.com/~rsc/regexp/regexp3.html(PCRE和RE2性能)
               
  3. REEC库
    REEC是一个精简,高效的C语言正则表达式引擎,它使得C语言开发中支持正则表达式,目前已经进化
    到了1.2.0版本,可以说无论从功能上,还是效率都到达了很好的应用水平,该引擎除支持常用的正则
    标准之外,还有一些原创的特性,例如正则式的分组、模式敏感等级等等,使得正则表达式更加灵活多变。 
    开源网站:
    		http://code.google.com/p/reec/
               

04.正则的简单运用

下面我通过3个小例子来让大家感受下正则的方便,因为我的编译器是C++,所以,我使用的是C++自己封装的正则库,如果是其他编译器,请参考其他博主

1.试图匹配正则表达式到整个字符序列 -----------regex_match()

2.试图匹配正则表达式到字符序列的任何部分 -----------regex_search()

3.以格式化的替换文本来替换正则表达式匹配的出现位置-----------regex_replace()

4.1母串是否匹配
regex_match() 该函数是查找母串是否匹配
#include <iostream>
#include <string>
#include <regex> //must be include
using namespace std;

void RegexDemo()
{
	regex split("[\\W\\w]+\\s[\\w]+\\s[\\w]+\\s[\\W\\w]+"); //这是规则
	//regex split("[A-Za-z]+\\s[a-z]+\\s[a-z]+\\s[A-Za-z]+"); 两个规则一样的效果,用那个舒服就用哪个
	//string s = "[JOG]#5->1000j,[CS1]5->1000X"; //这是母串
	string s = "Cain is an ItCast";  //这是母串
	smatch result; //这是存放找到的内容
	
	bool IsResult = regex_match(s,result,split);
	if(IsResult)
	{
		cout << "Matching is success...." <<endl;
		//输出内容之前要转换一下类型
		string content = result.str();  //内置方法转化为string
		cout << "result: " << content << endl; 
	}
	else
	{
		cout << "Matching is failed......" << endl;
	}
}

int main()
{
	RegexDemo();	

	system("pause");
	return 0;
}
           
4.2子串是否匹配(Working Example)
regex_search() 该函数是查找母串中是否匹配目标子串
#include <iostream>
#include <string>
#include <regex> //must be include
using namespace std;

void RegexDemo()
{
	regex split("[\\d]+\\X"); //这是规则
	//regex split([0-9]+[A-Z]"); 同上,但是这里适用,换了母串就不适用了,因为这个条件比较限制,自行体会。
	char* arr;
	string s = "[JOG]#5->1000j,[CS1]5->1000X"; //这是母串
	smatch result; //这是存放找到的内容
	
	bool IsResult = regex_search(s,result,split);
	if(IsResult)
	{
		cout << "Matching is success...." <<endl;
		//输出内容之前要转换一下类型
		string content = result.str();  //内置方法转化为string
		cout << "result: " << content << endl; 

	//我工作中的例子比较复杂,还要转好几次才可以用,如果想转成char*,我这里再写下
		arr = result.str().data();//这里就转成了char*
		cout << arr << endl;
	}
	else
	{//Matching failed(匹配失败)
		cout << "Matching is failed......" << endl;
	}
}

int main()
{
	RegexDemo();	

	system("pause");
	return 0;
}
           
4.3查找内容并替换
regex_replace() 该函数是查找母串中是否有复合条件的内容,如果有就替换为你想传入的字符串
#include <iostream>
#include <string>
#include <regex> //must be include
using namespace std;

void RegexDemo()
{
	regex split("[\\W\\w]+\\s[\\w]+\\s[\\w]+\\s[\\w]+");
	//regex split("[A-Za-z]+\\s[a-z]+\\s[a-z]+\\s[a-z]+");  //第二种写法 
	string s = "Maker is a pig";
	string content = "Cain is a people";

	string result = regex_replace(s,split,content);
	cout << result << endl; //替换失败与成功看内容
}

int main()
{
	RegexDemo();	

	system("pause");
	return 0;
}
           
上面的运行结果我都没有贴图片,但是亲测是No problem的,大家可以验证,上一篇正则有在线正则的链接。

05.正则求一些常用的字符串

这里我写两个

1.求点分十进制格式的Ip地址通用正则

2.求例如百度的网址的通用正则

5.1 点分十进制
#include <iostream>
#include <string>
#include <regex>
using namespace std;

int main()
{//这里就不封装了,直接main函数里写,内容不多
	regex split("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+");
	string s = "I am 192.168.0.1 的ip地址";
	smatch result;

	bool IsMatch = regex_search(s,result,split);
	if(IsMatch)
	{
		cout << "Matching is success......." <<endl;
		cout << result.str() << endl;
	}
	else
	{
		cout << "Matching is failed........" << endl; 
	}
	
	system("pause");
	return 0;
}
           

运行结果:

【Regular正则表达式】基础小练习(一)
5.2 网址(www.baidu.com等)
#include <iostream>
#include <string>
#include <regex>
using namespace std;

int main()
{//这里就不封装了,直接main函数里写,内容不多
	regex split("[a-z]+\\.[a-zA-Z0-9]+\\.[a-z]+");
	//上面是通配解决xxx.xxx.xxx格式的网址,如果是
	//www.abc.23.com则不再规则范围
	string s = "www.baidu.com//www.tech.52441.com";
	smatch result;

	bool IsMatch = regex_search(s,result,split);
	if(IsMatch)
	{
		cout << "Matching is success......." <<endl;
		cout << result.str() << endl;
	}
	else
	{
		cout << "Matching is failed........" << endl; 
	}
	
	system("pause");
	return 0;
}
           

运行结果:

【Regular正则表达式】基础小练习(一)

06.正则小练习一总结

【Regular正则表达式】基础小练习(一)

上面的内容都非常基础,涉及到了原字符和转义字符等的使用。

技术不高深,但是其实已经可以说明一些正则的优点了,我们平时处理字符串也就不过比这些格式更加复杂一点。

学习是一个盖楼的过程,基础的扎实相较开始就接触高深的技术来的更加踏实。

万丈高楼平地起,勿在浮沙建高楼;

版权声明:创作不易,转载请注明出处。