一文帶你簡(jiǎn)單了解c++正則表達(dá)式
1.正則表達(dá)式的需求
1.檢查一個(gè)串是否包含某種形式的子串;
2.將匹配的子串替換
3.從某個(gè)串中取出符合條件的子串。
1.1普通字符
普通字符包括沒(méi)有顯式指定為元字符的所有可打印和不可打印字符。這包括所有大寫(xiě)和小寫(xiě)字母、所有數(shù)字、所有標(biāo)點(diǎn)符號(hào)和一些其他符號(hào)。
1.2特殊字符
特殊字符是正則表達(dá)式里有特殊含義的字符,也是正則表達(dá)式的核心匹配語(yǔ)法。參見(jiàn)下表:
特殊字符 | 描述 |
$ | 匹配輸入字符串的末尾位置 |
* | 匹配前面的子表達(dá)零次或多次 |
+ | 匹配前面的子表達(dá)零次或多次 |
[ | 標(biāo)記一個(gè)中括號(hào)表達(dá)式開(kāi)始 |
? | 匹配前面子表達(dá)式零次或一次,或指明非貪婪限定符 |
\ | 將下一個(gè)字符標(biāo)記為或特殊字符、或原義字符、或向后引用、或八進(jìn)制轉(zhuǎn)義符。例如,n匹配字符n。\n 匹配換行符。序列\(zhòng)\匹配\字符,而\則匹配‘(·字符。 |
~ | 匹配輸人字符串的開(kāi)始位置,除非在方括號(hào)表達(dá)式中使用,此時(shí)它表示不接受該字符集合。 |
{ | 標(biāo)記限定符表達(dá)式開(kāi)始 |
\| | 指明兩項(xiàng)之間的一個(gè)選擇 |
補(bǔ)充:
(,)標(biāo)記一個(gè)子表達(dá)式的開(kāi)始和結(jié)束位置,子表達(dá)式可以供以后使用
. :匹配前面除\n之外的任何單字符
1.3限定字符
限定符用來(lái)指定正則表達(dá)式的一個(gè)給定的組件必須要出現(xiàn)多少次才能滿(mǎn)足匹配。見(jiàn)下表:
字符 | 描述 |
* | 匹配前面的子表達(dá)式零次或多次。例如,foo* 能匹配 fo 以及 foooo。* 等價(jià)于 {0,}。 |
+ | 匹配前面的子表達(dá)式一次或多次。例如,foo+ 能匹配 foo 以及 foooo,但不能匹配 fo。+ 等價(jià)于 {1,}。 |
? | 匹配前面的子表達(dá)式零次或一次。例如,Your(s)? 可以匹配 Your 或 Yours 中的 Your 。? 等價(jià)于 {0,1}。 |
{n} | n 是一個(gè)非負(fù)整數(shù)。匹配確定的 n 次。例如,o{2} 不能匹配 for 中的 o,但是能匹配 foo 中的兩個(gè) o。 |
{n,} | n 是一個(gè)非負(fù)整數(shù)。至少匹配 n 次。例如,o{2,} 不能匹配 for 中的 o,但能匹配 foooooo 中的所有 o。o{1,} 等價(jià)于 o+。o{0,} 則等價(jià)于 o*。 |
{n,m} | m 和 n 均為非負(fù)整數(shù),其中 n 小于等于 m。最少匹配 n 次且最多匹配 m 次。例如, o{1,3} 將匹配 foooooo 中的前三個(gè) o。o{0,1} 等價(jià)于 o?。注意,在逗號(hào)和兩個(gè)數(shù)之 間不能有空格。 |
2 std::regex極其相關(guān)
2.1regex_match
對(duì)字符串內(nèi)容進(jìn)行匹配的最常見(jiàn)手段就是使用正則表達(dá)式??上г趥鹘y(tǒng) C++ 中正則表達(dá)式一直沒(méi) 有得到語(yǔ)言層面的支持,沒(méi)有納入標(biāo)準(zhǔn)庫(kù),而 C++ 作為一門(mén)高性能語(yǔ)言,在后臺(tái)服務(wù)的開(kāi)發(fā)中,對(duì) URL 資源鏈接進(jìn)行判斷時(shí),使用正則表達(dá)式也是工業(yè)界最為成熟的普遍做法。
C++11 提供的正則表達(dá)式庫(kù)操作 std::string 對(duì)象,模式 std::regex (本質(zhì)是 std::basic_regex) 進(jìn)行初始化,通過(guò) std::regex_match 進(jìn)行匹配,從而產(chǎn)生 std::smatch(本質(zhì)是 std::match_results 對(duì)象)。
我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)簡(jiǎn)單介紹這個(gè)庫(kù)的使用。考慮下面的正則表達(dá)式:
[a-z]+\.txt: 在這個(gè)正則表達(dá)式中, [a-z] 表示匹配一個(gè)小寫(xiě)字母, + 可以使前面的表達(dá)式匹配多 次,因此 [a-z]+ 能夠匹配一個(gè)小寫(xiě)字母組成的字符串。在正則表達(dá)式中一個(gè) . 表示匹配任意字 符,而 \. 則表示匹配字符 .,最后的 txt 表示嚴(yán)格匹配 txt 則三個(gè)字母。因此這個(gè)正則表達(dá)式的 所要匹配的內(nèi)容就是由純小寫(xiě)字母組成的文本文件。
std::regex_match 用于匹配字符串和正則表達(dá)式,有很多不同的重載形式。最簡(jiǎn)單的一個(gè)形式就是 傳入 std::string 以及一個(gè) std::regex 進(jìn)行匹配,當(dāng)匹配成功時(shí),會(huì)返回 true,否則返回 false。例 如:
#include <iostream> #include <string> #include <regex> int main() { std::string fnames[] = {"foo.txt", "bar.txt", "test", "a0.txt", "AAA.txt"}; // 在 C++ 中 \ 會(huì)被作為字符串內(nèi)的轉(zhuǎn)義符,為使 \. 作為正則表達(dá)式傳遞進(jìn)去生效,需要對(duì) \ 進(jìn)行二次轉(zhuǎn)義,從而有 \\. std::regex txt_regex("[a-z]+\\.txt"); for (const auto &fname: fnames) std::cout << fname << ": " << std::regex_match(fname, txt_regex) << std::endl; }
結(jié)果:
foo.txt: 1
bar.txt: 1
test: 0
a0.txt: 0
AAA.txt: 0
另一種常用的形式就是依次傳入 std::string/std::smatch/std::regex 三個(gè)參數(shù),其中 std::smatch 的本質(zhì)其實(shí)是 std::match_results。在標(biāo)準(zhǔn)庫(kù)中,std::smatch 被定義為了 std::match_results, 也就是一個(gè)子串迭代器類(lèi)型的 match_results。使用 std::smatch 可以方便的對(duì)匹配的結(jié)果進(jìn)行獲取
#include<iostream> #include<string> #include<regex> int main() { std::string fnames[] = {"foo.txt", "bar.txt", "test", "a0.txt", "AAA.txt"}; // 在 C++ 中 \ 會(huì)被作為字符串內(nèi)的轉(zhuǎn)義符,為使 \. 作為正則表達(dá)式傳遞進(jìn)去生效,需要 std::regex base_regex("([a-z]+)\\.txt"); std::match_results<std::string::const_iterator> base_match; for(const auto& fname : fnames) { if(std::regex_match(fname,base_match,base_regex)) { // std::smatch 的第一個(gè)元素匹配整個(gè)字符串 // std::smatch 的第二個(gè)元素匹配了第一個(gè)括號(hào)表達(dá) if (base_match.size() == 2){ std::string base = base_match[1].str(); std::cout << "sub-match[0]: " << base_match[0].str() << std::endl; std::cout << fname << " sub-match[1]: " << base << std::endl; } } } }
sub-match[0]: foo.txt foo.txt
sub-match[1]: foo
sub-match[0]: bar.txt bar.txt
sub-match[1]: bar
2.2regex_replace and regex_search
regex_search:搜索匹配,即搜索字符串中存在符合規(guī)則的子字符串。
regex_replace: 替換匹配,即可以將符合匹配規(guī)則的子字符串替換為其他字符串。(會(huì)改變字符串本身)
測(cè)試代碼 regex_search:
#include<regex> #include<string> #include<iostream> int main() { std::string str = "hello2012-12-12world!!!!!"; std::match_results<std::string::const_iterator> match; std::regex pattern("(\\d{4})-(\\d{1,2})-(\\d{1,2})"); if (std::regex_search(str,match,pattern)) { for (size_t i = 1; i < match.size(); ++i) { std::cout << match[i] <<std:: endl; } } return 0; } // 2012 12 12
測(cè)試代碼:regex_replace
#include<regex> #include<string> #include<iostream> using namespace std; int main() { string str = "2019-08-07"; cout << regex_replace(str, regex("-"), "/") << endl; cout << str << endl; return 0; }
3 常用的regex
3.1檢驗(yàn)數(shù)字表達(dá)式
數(shù)字 : ^[0-9]*$
n 位的數(shù)字 : ^\d{n}$
至少 n 位的數(shù)字 : ^\d{n,}$
m-n 位的數(shù)字 : ^\d{m,n}$
零和非零開(kāi)頭的數(shù)字 : ^(0|[1-9][0-9]*)$
非零開(kāi)頭的最多帶兩位小數(shù)的數(shù)字 : ^([1-9][0-9]*)+(.[0-9]{1,2})?$
帶 1~2 位小數(shù)的正數(shù)或負(fù)數(shù) : ^(\-)?\d+(\.\d{1,2})?$
正數(shù) , 負(fù)數(shù) , 和小數(shù) : ^(\-|\+)?\d+(\.\d+)?$
有兩位小數(shù)的正實(shí)數(shù) : ^[0-9]+(.[0-9]{2})?$
有 1~3 位小數(shù)的正實(shí)數(shù) : ^[0-9]+(.[0-9]{1,3})?$
非零的正整數(shù) : ^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的負(fù)整數(shù) : ^\-[1-9][]0-9″*$ 或 ^-[1-9]\d*$
非負(fù)整數(shù) : ^\d+$ 或 ^[1-9]\d*|0$
非正整數(shù) : ^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非負(fù)浮點(diǎn)數(shù) : ^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮點(diǎn)數(shù) : ^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮點(diǎn)數(shù) : ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
負(fù)浮點(diǎn)數(shù) : ^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮點(diǎn)數(shù) : ^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
3.2檢驗(yàn)字符串表達(dá)式
漢字 : ^[\u4e00-\u9fa5]{0,}$
英文和數(shù)字 : ^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
長(zhǎng)度為 3~20 的所有字符 : ^.{3,20}$
由 26 個(gè)英文字母組成的字符串 : ^[A-Za-z]+$
由 26 個(gè)大寫(xiě)英文字母組成的字符串 : ^[A-Z]+$
由 26 個(gè)小寫(xiě)英文字母組成的字符串 : ^[a-z]+$
由數(shù)字和 26 個(gè)英文字母組成的字符串 : ^[A-Za-z0-9]+$
由數(shù)字 , 26 個(gè)英文字母或者下劃線(xiàn)組成的字符串 : ^\w+$ 或 ^\w{3,20}$
中文 , 英文 , 數(shù)字包括下劃線(xiàn) : ^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文 , 英文 , 數(shù)字但不包括下劃線(xiàn)等符號(hào) : ^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以輸入含有^%&',;=?$\"等字符 : [^%&',;=?$\x22]+
禁止輸入含有 ~ 的字符 : [^~\x22]+
3.3檢驗(yàn)特殊表達(dá)式
Email 地址 : ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名 : [a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
InternetURL : [a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手機(jī)號(hào)碼 : ^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
電話(huà)號(hào)碼("XXX-XXXXXXX" , "XXXX-XXXXXXXX" , "XXX-XXXXXXX" , "XXX-XXXXXXXX" , "XXXXXXX"和"XXXXXXXX) : ^($$\d{3,4}-)|\d{3.4}-)?\d{7,8}$
國(guó)內(nèi)電話(huà)號(hào)碼 (0511-4405222 , 021-87888822) : \d{3}-\d{8}|\d{4}-\d{7}
身份證號(hào) (15 位 , 18 位數(shù)字) : ^\d{15}|\d{18}$
短身份證號(hào)碼 (數(shù)字 , 字母 x 結(jié)尾) : ^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
帳號(hào)是否合法(字母開(kāi)頭,允許 5~16 字節(jié),允許字母數(shù)字下劃線(xiàn)) : ^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密碼 (以字母開(kāi)頭,長(zhǎng)度在 6~18 之間,只能包含字母 , 數(shù)字和下劃線(xiàn)) : ^[a-zA-Z]\w{5,17}$
強(qiáng)密碼 (必須包含大小寫(xiě)字母和數(shù)字的組合,不能使用特殊字符,長(zhǎng)度在 8~10 之間) : ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式 : ^\d{4}-\d{1,2}-\d{1,2}
一年的 12 個(gè)月(01~09和1~12) : ^(0?[1-9]|1[0-2])$
一個(gè)月的 31 天(01~09和1~31) : ^((0?[1-9])|((1|2)[0-9])|30|31)$
注意:
在C++中,對(duì)于特殊字符,需要使用轉(zhuǎn)義字符. 因此,匹配數(shù)字的\d,需要寫(xiě)成\d這種格式.
經(jīng)典的三部曲匹配:
1.先寫(xiě)pattern. string pattern = {“XXXX”};
2.使用re. regex re(pattern);
3.match. bool rs = regex_match(mobile, re);
4.regex_match在匹配一次后即返回結(jié)果,如果期望進(jìn)行多次匹配,需要用到regex_iterator.std::regex_iterator<std::string::iterator> rit(result.begin(), result.end(), re); 匹配結(jié)果的輸出可以利用cmatch.regex_match(rit->str().c_str(), cm, re);這里面cm的內(nèi)容與正則表達(dá)式pattern是對(duì)應(yīng)匹配的. 具體可參考matchPriceInfo方法.
總結(jié)
到此這篇關(guān)于c++正則表達(dá)式的文章就介紹到這了,更多相關(guān)c++正則表達(dá)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++?opencv圖像處理實(shí)現(xiàn)灰度變換示例
這篇文章主要為大家介紹了C++?opencv圖像處理灰度變換的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05QT實(shí)現(xiàn)TCP網(wǎng)絡(luò)聊天室
這篇文章主要為大家詳細(xì)介紹了QT實(shí)現(xiàn)TCP網(wǎng)絡(luò)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08Qt實(shí)現(xiàn)可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器
計(jì)算器是我們生活中很常見(jiàn)的東西,它可以由多種語(yǔ)言多種方式來(lái)實(shí)現(xiàn)。本文主要介紹的是基于C++語(yǔ)言,由QT實(shí)現(xiàn)的可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器,需要的可以參考一下2022-12-12C++結(jié)構(gòu)體作為函數(shù)參數(shù)傳參的實(shí)例代碼
這篇文章主要介紹了C++結(jié)構(gòu)體作為函數(shù)參數(shù)傳參的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12C語(yǔ)言深入探索數(shù)據(jù)類(lèi)型的存儲(chǔ)
使用編程語(yǔ)言進(jìn)行編程時(shí),需要用到各種變量來(lái)存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類(lèi)型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類(lèi)型,來(lái)分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么2022-07-07c++ 數(shù)據(jù)結(jié)構(gòu)map的使用詳解
這篇文章主要介紹了c++ 數(shù)據(jù)結(jié)構(gòu)map的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用c++,感興趣的朋友可以了解下2021-04-04C語(yǔ)言完美實(shí)現(xiàn)動(dòng)態(tài)數(shù)組代碼分享
本文給大家分享的是一則使用C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)數(shù)組的代碼,完美解決內(nèi)存溢出以及內(nèi)存回收問(wèn)題,有需要的小伙伴可以參考下。2016-02-02C語(yǔ)言中的運(yùn)算符優(yōu)先級(jí)和結(jié)合性一覽表
這篇文章主要介紹了C語(yǔ)言中的運(yùn)算符優(yōu)先級(jí)和結(jié)合性一覽表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02