新普京网站-澳门新普京 > 前端 > 中正则表达式使用示例及源码分析

中正则表达式使用示例及源码分析

2019/12/29 20:17

正则表明式Regex(regular expression卡塔尔国是风流倜傥种强盛的描述字符体系的工具。在广大语言中都留存着正则表明式,C++11中也将正则表明式放入了新专门的学问的一片段,不止如此,它还协助了6种差异的正则表明式的语法,分别是:ECMASC瑞虎IPT、basic、extended、awk、grep和egrep。个中ECMASCTiggoIPT是暗中认可的语法,具体接收哪个种类语法大家得以在布局正则表达式的时候钦命。

注:ECMAScript是风流潇洒种由Ecma国际(前身为南美洲Computer创设商协会,罗马尼亚语名称是European Computer Manufacturers Association)通过ECMA-262尺码的本子程序设计语言。它往往被喻为JavaScript,但实质上后面一个是ECMA-262正规的兑现和增加。

下边大家就以本篇博客的页面(

确认保障您的编写翻译器扶持Regex

设若您的编译器是GCC-4.9.0可能VS二〇一一之下版本,请晋级后,再利用。自笔者前面运用的C++编写翻译器,是GCC 4.8.3,有regex头文件,可是GCC特别不老实的未有贯彻,语法完全援救,不过库尚未跟上,所以编写翻译的时候是不曾难题的,可是一运转就能够平昔抛出拾壹分,特别周全的叁个坑有木有!具体错误如下:

terminate called after throwing an instance of 'std::regex_error'
  what():  regex_error
Aborted (core dumped)

假若您也越过了这几个主题素材,请不要先狐疑自个儿,GCC那点是那几个坑爹的!!!笔者在此个地方浪费了半天的时日才找了出来。所以在尝鲜C++的正则表明式以前,请进级你的编写翻译器,确定保证您的编译器帮助它。

regex库概览

在头文件<regex>中隐含了多少个我们应用正则表达式时供给接收的组件,大致有:

basic_regex 正则表达式对象,是一个通用的模板,有typedef basic_regex<char> regex 和 typedef basic_regex<char_t>wregex;
regex_match 将一个字符序列和正则表达式匹配
regex_search 寻找字符序列中的子串中与正则表达式匹配的结果,在找到第一个匹配的结果后就会停止查找
regex_replace 使用格式化的替换文本,替换正则表达式匹配到字符序列的地方
regex_iterator 迭代器,用来匹配所有 的子串
match_results 容器类,保存正则表达式匹配的结果。
sub_match 容器类,保存子正则表达式匹配的字符序列.

ECMASCTiguanIPT正则表达式语法

正则表达式式的语法基本如出生机勃勃辙,在那间就浪费篇幅细抠了。ECMASC途锐IPT正则表达式的语法知识能够参照W3CSCHOOL。

协会正则表明式

布局正则表明式用到三个类:basic_regex。basic_regex是二个正则表达式的通用类模板,对char和wchar_t类型都有对应的特化:

typedef basic_regex<char>    regex;
typedef basic_regex<wchar_t> wregex;

布局函数非常多,可是特轻便:

//默认构造函数,将匹配任何的字符序列
basic_regex();
//用一个以‘’结束的字符串s构造一个正则表达式
explicit basic_regex( const CharT* s,flag_type f =std::regex_constants::ECMAScript );
//同上,但是制定了用于构造的字符串s的长度为count
basic_regex( const CharT* s, std::size_t count,flag_type f = std::regex_constants::ECMAScript );
//拷贝构造,不赘述
basic_regex( const basic_regex& other );
 //移动构造函数
basic_regex( basic_regex&& other );
//以basic_string类型的str构造正则表达式
template< class ST, class SA >
explicit basic_regex( const std::basic_string<CharT,ST,SA>& str, flag_type f = std::regex_constants::ECMAScript );
//指定范围[first,last)内的字符串构造正则表达式
template< class ForwardIt >
basic_regex( ForwardIt first, ForwardIt last, flag_type f = std::regex_constants::ECMAScript );
//使用initializer_list构造
basic_regex( std::initializer_list<CharT> init, flag_type f = std::regex_constants::ECMAScript );

如上巳默许布局之外的布局函数,都有叁个flag_type类型的参数用于指定正则表明式的语法,ECMASCHavalIPT、basic、extended、awk、grep和egrep均是可选的值。除却还应该有任何二种只怕的的标识,用于转移正则表明式相配时的法则和作为:

flag_type effects
icase 在匹配过程中忽略大小写
nosubs 不保存匹配的子表达式
optimize 执行速度优于构造速度

有了布局函数之后,今后我们就足以先布局出三个领到http链接的正则表明式:

std::string pattern("http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?");    //匹配规则很简单,如果有疑惑,可以对照语法查看
std::regex r(pattern);

值得后生可畏提的是在C++中’'这些字符必要转义,因而全体ECMASCWranglerIPT正则表达式语法中的’'都须求写成“\”的形式。我测量试验的时候,这段regex若无加转义,在gcc中会给出警报提醒,vs2011编译后后运营直接崩溃了。

对的地拍卖输入

先扯叁个题外话,假诺大家不是使用了互连网库自动在前后相继中下载的网页,在我们手动下载了网页并保留到文件后,首先咱们要做的依然先把网页的从头到尾的经过(html源码卡塔尔国存入三个std::string中,大家恐怕会接受那样的荒唐格局:

int main()
{
    std::string tmp,html;
    while(std::cin >> tmp)
        html += tmp;
}

那样一来源代码中具备的空白字符就无形中中被大家全管理了,这明显不合适。这里大家照旧选取getline(卡塔尔国那一个函数来处理:

int main()
{
    std::string tmp,html;
    while(getline(std::cin,tmp))
    {
        html += tmp;
        html += 'n';
    }
}

那样一来原本的公文本领收获不错的输入。当然民用感觉那一个小细节依旧值得注意的,届时候出错debug的时候,小编想大家更加多地多疑的是团结的正则表达式是还是不是是有效

regex_search(State of Qatar只查找到第一个非常的子体系

据书上说函数的字面语义,大家大概会错误的精选regex_search(卡塔尔(قطر‎那么些函数来进展相称。其函数原型也会有6个重载的版本,用法也是相差无几,函数再次回到值是bool值,成功重返true,败北重返false。鉴于篇幅,大家只看大家上面要接纳的这一个:

template< class STraits, class SAlloc,class Alloc, class CharT, class Traits >
bool regex_search( const std::basic_string<CharT,STraits,SAlloc>& s,
                   std::match_results<typename std::basic_string<CharT,STraits,SAlloc>::const_iterator, Alloc>& m,
                   const std::basic_regex<CharT, Traits>& e,
                   std::regex_constants::match_flag_type flags = std::regex_constants::match_default );

先是个参数s是std::basic_string类型的,它是我们待相配的字符系列,参数m是一个match_results的器皿用于寄放相配到的结果,参数e则是用来贮存大家事情发生前协会的正则表明式对象。flags参数值得意气风发提,它的档期的顺序是std::regex_constants::match_flag_type,语义上相配标记的意味。正如在布局正则表明式对象时大家得以内定选项如哪个地点理正则表明式同样,在合营的长河中大家依然得以钦命其它的声明来决定格外的条条框框。那个标记的切实可行意思,笔者从cppreference.com 引用过来,用的时候查一下就足以了:

Constant Explanation
match_not_bol The first character in [first,last) will be treated as if it is not at the beginning of a line (i.e. ^ will not match [first,first)
match_not_eol The last character in [first,last) will be treated as if it is not at the end of a line (i.e. $ will not match[last,last)
match_not_bow "b" will not match [first,first)
match_not_eow "b" will not match [last,last)
match_any If more than one match is possible, then any match is an acceptable result
match_not_null Do not match empty sequences
match_continuous Only match a sub-sequence that begins at first
match_prev_avail --first is a valid iterator position. When set, causes match_not_bol and match_not_bow to be ignored
format_default Use ECMAScript rules to construct strings in std::regex_replace (syntax documentation)
format_sed Use POSIX sed utility rules in std::regex_replace. (syntax documentation)
format_no_copy Do not copy un-matched strings to the output in std::regex_replace

基于参数类型,于是我们组织了这般的调用:

std::smatch results;<br>regex_search(html,results,r);

不过,标准库规定regex_search(State of Qatar在寻找到第二个十三分的子串后,就能够终止查找!在本程序中,results参数只带回了第三个知足条件的http链接。那显然并无法满足大家要提取网页中持有HTTP链接必要。

使用regex_iterator相配全部子串

适度从紧意义上regex_iterator是意气风发种迭代器适配器,它用来绑定要协作的字符体系和regex对象。regex_iterator的暗许构造函数相比较优质,就径直组织了多个尾后迭代器。别的贰个结构函数原型:

regex_iterator(BidirIt a, BidirIt b,                                                           //分别是待匹配字符序列的首迭代器和尾后迭代器
               const regex_type& re,                                                           //regex对象
               std::regex_constants::match_flag_type m = std::regex_constants::match_default); //标志,同上面的regex_search()中的

和上边的regex_search()一样,regex_iterator的结构函数中也可能有std::regex_constants::match_flag_type类型的参数,用法同样。其实regex_iterator的里边得以完结便是调用了regex_search(卡塔尔(قطر‎,这么些参数是用来传递给regex_search(State of Qatar的。用gif或者能够演示的可比形象一点,具体是如此专门的学问的(颜色加深部分,表示可以合作的子系列):

图片 1

第一在协会regex_iterator的时候,布局函数中率先就调用三次regex_search(State of Qatar将迭代器it指向了第三个门户大概的子类别。以往的每次迭代的进程中(++it),都会在之后剩下的子连串中三番五次调用regex_search(卡塔尔国,直到迭代器走到终极。it就平昔“指向”了合作的子种类。

知道了规律,大家写起来代码就轻巧多了。结合前边的有些我们,那一个顺序就着力写好了:

#include <iostream>
#include <regex>
#include <string>

int main()
{
    std::string tmp,html;
    while(getline(std::cin,tmp))
    {
        tmp += 'n';
        html += tmp;
    }
    std::string pattern("http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?”);
    pattern = “[[:alpha:]]*” + pattern + “[[:alpha:]]*”;
    std::regex r(pattern);
    for (std::sregex_iterator it(html.begin(), html.end(), r), end;     //end是尾后迭代器,regex_iterator是regex_iterator的string类型的版本
        it != end;
        ++it)
    {
        std::cout << it->str() << std::endl;
    }
}

下载本页的html源码保存为test.html,编写翻译这些源码测验一下,顺理成章:

[regex]g++ regex.cpp  -std=c++11 -omain
[regex]main < test.html

http://www.cnblogs.com/ittinybird/rss


http://www.cnblogs.com/ittinybird/rsd.xml


http://www.cnblogs.com/ittinybird/wlwmanifest.xml


http://common.cnblogs.com/script/jquery.js


http://files.cnblogs.com/files/ittinybird/mystyle.css


http://www.cnblogs.com/ittinybird/


http://www.cnblogs.com/ittinybird/


http://www.cnblogs.com/ittinybird/


http://i.cnblogs.com/EditPosts.aspx?opt=1


http://msg.cnblogs.com/send/%E6%88%91%E6%98%AF%E4%B8%80%E5%8F%AAC%2B%2B%E5%B0%8F%E5%B0%8F%E9%B8%9F


http://www.cnblogs.com/ittinybird/rss


http://www.cnblogs.com/ittinybird/rss


http://www.cnblogs.com/images/xml.gif


http://i.cnblogs.com/


http://www.cnblogs.com/ittinybird/p/4853532.html


http://www.cnblogs.com/ittinybird/p/4853532.html


http://www.w3school.com.cn/jsref/jsref_obj_regexp.asp


http://www.cnblogs.com/ittinybird/


http://i.cnblogs.com/EditPosts.aspx?postid=4853532


http://www.cnblogs.com/


http://q.cnblogs.com/


http://news.cnblogs.com/


http://home.cnblogs.com/ing/


http://job.cnblogs.com/


http://kb.cnblogs.com/

regex和丰裕管理

只要大家的正则表明式存在似是而非,则在运营的时候正规库会抛出七个regex_error极度,他有三个名称为code的分子,用于标志错误的等级次序,具体错误值和语义如下表所示:

code 含义
error_collate 无效的元素校对
error_ctype 无效的字符类
error_escape 无效的转移字符或者无效的尾置转义
error_backref 无效的向后引用
error_brack 方括号不匹配
error_paren 小括号不匹配
error_brace 大括号不匹配
error_badbrace 大括号中的范围无效
error_range 无效的(不合法)字符范围
error_space 内存不足
error_badrepeat 重复字符之前没有正则表达式(* + ?)
error_complexity 太复杂了,标准库君hold不住了
error_stack 栈空间不足了

至于十分管理的核心内容,不是本篇要研究的剧情,就不赘述了。

小结

C++11标准库中的正则表达式部分还也是有部分剧情本文没有涉及,个人认为精晓了以上的内容后,基本上看生龙活虎看接口就通晓怎么利用了,这里就不浪费篇幅了。

多谢您的读书,错误之处还请你斧正,笔者将特别多谢。

上一篇:前端单元测验计算及测量检验工具介绍,的测验驱动开垦 下一篇:没有了