C++ boost 正則表達式用法

 

什麼是正則表達式?正則表達式是一種用來描述必定數量文本的模式。Regex表明Regular Express。
若是您不知道什麼是正則表達式,請看這篇文章http://blog.csdn.net/begtostudy/archive/2007/11/11/1879206.aspxios

有了正則表達式的基礎,問題是如何使用。咱們以boost::regex來講正則表達式

先看一個網上經典的例子。算法

#include "stdafx.h"express

#include <cstdlib>函數

#include <stdlib.h>測試

#include <boost/regex.hpp>ui

#include <string>編碼

#include <iostream>spa

using namespace std;.net

using namespace boost;

regex expression("^select ([a-zA-Z]*) from ([a-zA-Z]*)");

int main(int argc, char* argv[])

{

std::string in;

cmatch what;

cout << "enter test string" << endl;

getline(cin,in);

if(regex_match(in.c_str(), what, expression))

{

for(int i=0;i<what.size();i++)

cout<<"str :"<<what[i].str()<<endl;

}

else

{

cout<<"Error Input"<<endl;

}

return 0;

}
 
==============
結果
輸入:select name from table

輸出:str:select name from table

str:name

str:table

按照咱們的要求,字符串被匹配挑出來了。
這在處理大量規則的文本格式的時候頗有用,由於它很靈活,一通百通。

首先,即便你擁有了boost庫,也須要單獨編譯regex。
若是你不知道boost庫,看這裏http://www.stlchina.org/twiki/bin/view.pl/Main/BoostStartIntroduce

網上的介紹:
boost庫安裝比較麻煩,須要本身編譯源文件,我整理了一下,若是僅僅須要作正則表達式,按下面的代碼敲就好了:

cmd

vcvars32.bat

cd D:\boost_1_32_0\libs\regex\build

d:

nmake -fvc6.mak

nmake -fvc6.mak install

注意,別看下載下來的數據包沒有多大,解壓縮以後達到了100多M,編譯完以後爲109M,佔用131M,因此安裝時必定注意空出足夠的空間,敲入nmake -fvc6.mak後等待的時間比較長,屏幕上還會出現一大堆英語,能夠不作考慮。按照步驟往下敲就好了。壓縮包內文檔很詳細,參照文檔繼續就能夠了。

在VC6中集成:Tools->Options->Directories->Include files

加入:D:\boost_1_32_0

我用的是VS2003
作了run.bat

chdir E:\Program\boost_1_34_1

bjam "-sTOOLS=vc-7_1" "-sVC71_ROOT=D:\Program Files\Microsoft Visual Studio .NET 2003\Vc7"  "--prefix=E:\Program\boost" "--builddir=E:\Program\boost_1_34_1\build" "-sBUILD=debug release <runtime-link>static/dynamic" --with-regex install

PAUSE

至於參數,須要參考boost安裝介紹http://blog.csdn.net/begtostudy/archive/2007/11/11/1879213.aspx

其餘的一些介紹

 bool validate_card_format(const std::string s)
        {
           static const boost::regex e("(\\d{4}[- ]){3}\\d{4}");
           return regex_match(s, e);
        }

boost::regex的默認正則表達式語法是perl語法
        boost::regex支持perl regular表達式、POSIX-Extended regular表達式和POSIX-Basic Regular表達式,但默認的表達式語法是perl語法,若是要使用其他兩種語法須要在構造表達式的時候明確指定。

        例如,下面兩種方法效果相同
        // e1 is a case sensitive Perl regular expression:
        // since Perl is the default option there''s no need to explicitly specify the syntax used here:
        boost::regex e1(my_expression);
        // e2 a case insensitive Perl regular expression:
        boost::regex e2(my_expression, boost::regex::perl|boost::regex::icase);

perl正則表達式語法
        perl正則表達式語法可參見《perl語言入門》第七、八、9章或boost的文檔。這裏列出的語法是不全面的,並且部分說明可能並不清楚。

        . 任意字符;使用match_no_dot_null標誌時不匹配NULL字符; 使用match_not_dot_newline時不匹配換行字符

        ^ 匹配行的開始
        $ 匹配行的結束
        * 重複零次或則更多,例如a*b可匹配b,ab,aab,aaaaaaab
        + 重複一次以上,例如a+b可匹配ab,aab,aaaaaaaab。但不能匹配b了
        ? 零次或則一次,例如ca?b匹配cb,cab但不匹被caab   
        a{n} 匹配字符''a''重複n次
        a{n,},字符a重複n次以上(含n次)
        a{n,m} a重複n到m次(含)

        *?   匹配前一個原子零次以上
        +?   匹配前一個原子一次以上
        ??   匹配前一個原子零次以上
        {n,}?  匹配前一個原子n次以上(含)
        {n,m?  匹配前一個原子n到m次(含)

        | 或操做,例如ab(d|ef)匹配abd或則abef
        [] 字符集操做,例如[abc]將匹配任何單個字符''a'',''b'',''c''
        [a-d],表示a、b、c、d
        ^否操做,例如[^a-c]表示a至c以外的全部字符


boost::regex對unicode編碼的支持
        boost::regex使用ICU來實現對unicode及unicode變種的支持,這須要在編譯boost的時候指出是否使用ICU以及ICU所在的目錄。不然編譯出來的boost::regex不支持unicode編碼。其中boost::wregex支持unicode編碼的搜索,若是要搜索UTF-八、UTF-1六、UFT-32編碼的字符串,則要用boost::u32regex。注意boost::wregex只能支持unicode編碼,不能支持uft編碼。

搜索時如何忽略大小寫
        若是要在搜索時忽略大小寫(即大小寫不敏感),則要用到表達式選項boost::regex::icase,例如: boost::regex e2(my_expression, boost::regex::perl|boost::regex::icase);

 


模板類:
l         basic_regex          用來保存一個「正則表達式」的類。
l         sub_match            繼承於pair<Iterator,Iterator>迭代器組,用來表示匹配的一個結果。
l         match_results             sub_match的容器,用來表示一次搜索或匹配算法的全部結果,相似於vector<sub_match>。
算法:
l         regex_math   匹配算法,測試一個字符串是否和一個正則式匹配,並經過match_results返回結果。
l         regex_find     查找算法,查找字符串的一個和正則式匹配的字串,並經過match_results返回結果。
l         regex_format       替換算法,查找字符串中的全部匹配正則式的字串,並使用「格式化字符」串替換。
迭代器:
l         regex_iterator      枚舉一個字符串中全部匹配的字串,regex_iterator的結果至關於match_results。
l         regex_token_iterator 枚舉一個字符串中全部匹配的字串,regex_iterator的結果至關於sub_match。
 
詳述

l       basic_regex


template <class charT, class traits = regex_traits<charT>, class Allocator = std::allocator<charT>  >

class basic_regex;

typedef basic_regex<char> regex;

typedef basic_regex<wchar_t> wregex;

很明顯,charT是正則式的字符類型,regex和wregex是basic_regex的兩個特化。
注意,正則式的字符類型要和須要匹配的字符串的字符類型相同。例如:不能在regex_find算法中分別使用string和wregex最爲參數,要麼是string和regex,要麼是wstring和wregex。
構造函數:
basic_regex re
 產生空的正則式
 
basic_regex re(str)
 正則式爲str,str能夠爲basic_string,也能夠是0結尾的char*字符串。
 
Basic_regex re(re2)
 拷貝構造。
 
basic_regex re(str,flag)
 正則式爲str,使用flag語法選項,flag是一組常量的組合。例如:icase可使正則式匹配忽略大小寫。
 
basic_regex re(beg,end)
 使用迭代器構造正則式。能夠是basic_string的迭代器,也能夠是const char*。
 
basic_regex re(beg,end,flag)
 使用迭代器構造正則式,flag是語法選項。
 


經常使用的語法選項:
regex_constants::normal
 默認的語法。符合EMCAScript,JavaScript中的正則式。
 
regex_constants::icase
 匹配的時候忽略大小寫。
 
regex_constants::nosubs
 不把匹配的子串保存進match_results結構。
 
regex_constants::collate
 對於[a-b]的匹配,考慮地區
 


 
語法選項經過或運算來結合。在basic_regex中這些語法選項也進行了定義,因此能夠寫成regex::normal,這要比regex_constants少打好幾個字母了吧!J
assign成員函數:
re.assign(re2)
 複製一個正則式
 
re.assign(str)
 正則式爲str。
 
re.assign(str, flag)
 正則式爲str,使用flag語法選項,flag是一組常量的組合。
 
re.assign(beg, end)
 使用迭代器構造正則式。
 
re.assign(beg, end, flag)
 使用迭代器構造正則式,flag是語法選項。
 


 
其實basic_regex不少用法和basic_string很像,由於正則表達式也是個字符串嘛!
迭代器:
regex::iterator it
 常迭代器類型,即const_iterator
 
re.begin()
 返回的是常迭代器哦!const_iterator
 
re.end()
 沒有逆向迭代器。
 


例如:copy(re.begin(), re.end(), ostream_iterator<char>(cout));
其餘:
re.size()
 正則表達式長度,即str的長度。
 
re.max_size()
 正則表達式的最大長度。
 
re.empty()
 長度是否爲0
 
re.mark_count()
 返回正則式的組數,通常狀況下爲小括號對數+1。在boost.regex中使用小括號分組,詳情請看下面的算法詳解。
 
re.flags()
 返回語法選項。
 
cout<<re
 正則式的流輸出,至關於上面示例的copy算法。
 
swap
 成員函數,全局函數都有
 
re.imbue(loc)
 設置local爲loc,返回原來的local
 
re.getloc()
 獲得當前local
 
==,!=,<,<=,>,>=
 比較運算符重載
 


 
l       sub_match
sub_match是一個迭代器組,表示正則式中的一個匹配。


template <class BidirectionalIterator>

class sub_match : public std::pair<BidirectionalIterator, BidirectionalIterator>;

boost沒有提供sub_match的任何特化,由於咱們不會顯示的聲明一個sub_match變量。sub_match是做爲match_results的元素用的。好比:match_results的operator[]和迭代器返回的就是一個特化的sub_match。
惟一的成員變量:
bool matched  是否匹配。
成員函數:
length()
 返回長度,即兩個迭代器之間的距離。
 
operator basic_string< value_type>()
 隱式的basic_string轉換。
 
str()
 顯式的basic_string轉換。
 


還有就是一大堆的比較操做符的重載了,這裏就很少說了。
 
l       match_results
match_results至關於sub_match的容器,用於表示正則式算法的返回結果。


template <class BidirectionalIterator,

          class Allocator = allocator<sub_match<BidirectionalIterator> >

class match_results;

 

typedef match_results<const char*> cmatch;

typedef match_results<const wchar_t*> wcmatch;

typedef match_results<string::const_iterator> smatch;

typedef match_results<wstring::const_iterator> wsmatch;

聲明很簡單,有四個特化能夠直接使用,不過要注意string和char*字符串使用的match_results是不一樣的。
成員函數:
m.size()
 容量。
 
m.max_size()
 最大容量。
 
m.empty()
 容量是否爲0。
 
m[n]
 第n個元素,即sub_match
 
m.prefix()
 返回表明前綴的sub_match,前綴指字符串的開頭到第一個匹配的開頭。
 
m.suffix()
 返回表明後綴的sub_match,後綴之最後一個匹配的結尾到字符串的結尾。
 
m.length(n)
 返回第n個元素的長度,即m[n].size()。
 
m.position(n)
 返回第n個元素的位置。
 
cout<<m
 流輸出,輸出整個匹配,至關於cout<<m[0]。由於第0個元素是整個匹配,詳細狀況請看下面的解釋。
 
m.format(fmtstr)
 使用格式化字符串,格式化結果,返回字符串
 
m.format(fmtstr,flags)
 使用格式化字符串,格式化結果,返回字符串,flags是格式化選項。
 
m.format(out,fmtstr)
 同上,可是使用輸出迭代器輸出結果。
 
m.format(out.fmtstr,flags)
 同上,可是使用輸出迭代器輸出結果。
 


迭代器:
smatch::iterator
 迭代器,常迭代器
 
smatch::const_iterator
 同上
 
m.begin()
 返回常迭代器
 
m.end()
 同上
 
 

最後,說一個實例

我處理一個文本

            實際值/-20.031,-1.896,-2.861,-1,0,0

提取其中的數字

regex exp("\s*實際值/(-?[0-9.]+),(-?[0-9.]+),(-?[0-9.]+),(-?[0-9.]+),(-?[0-9.]+),(-?[0-9.]+)$");

你們看看還有沒有更好的寫法?

 

 

regex_match

regex_match算法用來測試一個字符串是否徹底匹配正則式。讓咱們來看一下regex_match的使用:

if (regex_match(str, m, re))

{

    ...

}

str是一個字符串,能夠是stringwstringchar *或者wchar_t *

mmatch_results,它經過引用傳入參數,來保存匹配的結果,m要和str的類型匹配,能夠是smatchwsmatchcmatchwcmatch,用來分別對應stringwstringchar *或者wchar_t*str

re就是正則表達式了,通常來講是regexwregex

strmre的類型以下:

str類型

m類型

re類型

string

smatch (match_results<string::const_iterator>)

regex (basic_regex<char>)

wstring

wsmatch (match_results<wstring::const_iterator>)

wregex (basic_regex<wchar_t>)

char*

cmatch (match_results<const char*>)

regex (basic_regex<char>)

wchar_t*

wcmatch (match_results<const wchar_t*>)

wregex (basic_regex<wchar_t>)

 

函數的返回值表示字符串是否徹底匹配正則表達式,當返回true的時候,m保存了匹配的結果;返回falsem未定義。

下面讓咱們來看一下,當函數返回true的時候,m是怎麼樣的。

m.size() == re.mark_count()

還記得re.mark_count()返回的是什麼嗎?在上一篇中說的是re.mark_count()返回的時正則式的「組數」,並無詳細解釋。這裏我要詳細解釋一下。

其實,這個「組數」在boostregex中叫作sub-expressionsub-expression就是在正則式中使用小括號括起來的一部分,正則式自己是一個sub-expression,因此re.mark_count()等於小括號對數+1

m.prefix()m.suffix()

這兩個返回的是sub_match類型(至關於一個迭代器組)。在regex_match算法中,這兩個返回的sub_match都是空的,他們的值以下:(sub_match繼承於pair,因此有firstsecond成員哦)

m.prefix().first == str.begin()

m.prefix().second == str.begin()

m.prefix().matched == false

m.suffix().first == str.end()

m.suffix().second == str.end()

m.suffix().matched == false

由於regex_match是徹底匹配,即整個字符串和正則式匹配,因此前綴和後綴都是空的。

m[0]

返回第0個匹配的,因爲regex_match是徹底匹配,因此

m[0].first == str.begin()

m[0].second == str.end()

m[0].matched == true

m[n] , n<m.size()

返回第n個匹配的sub-expression

m[n].matched 表示第nsub-expression是否在字符串中存在。整個regex匹配,可是sub_exp可能匹配的是空的,例如」(a*)」就有能夠匹配空。

m[n].firstm[n].second 表示匹配的範圍。若是匹配空的話,都爲str.end()

 

根據個人測試,m[1],m[2],...,m[n]的順序是按照正則式的左小括號的順序來的,例如對於正則式」((a)bc)d(efg)」,若是匹配了一個字符串的話(字符串只多是」abcdefg」),則

m[0] == 「abcdefg」  sub_match重載了==運算符使得能夠和一個字符串比較)

m[1] == 「abc」

m[2] == 「a」

m[3] == 「efg」

 

regex_match的其它用法

regex_match(str,re)

只測試是否匹配,不須要匹配的結果

regex_match(beg,end,re)

輸入的是迭代器

regex_match(beg,end,m,re)

注意m的類型爲match_results<iterator>

regex_match(str,m,re,flag)

flag是匹配選項,默認是的regex_constants::match_default

 

regex_search

regex_search的用法基本上和regex_match同樣。

if (regex_search(str, m, re))

{

    ...

}

regex_search不要求str徹底匹配re,只要str中的一個字串匹配re就能夠了。因此,m.prefix()m.suffix()不必定爲空。

regex_search是從左往右匹配,並且儘可能匹配長的字串。 

相關文章
相關標籤/搜索