一文帶你簡單了解c++正則表達式
1.正則表達式的需求
1.檢查一個串是否包含某種形式的子串;
2.將匹配的子串替換
3.從某個串中取出符合條件的子串。
1.1普通字符
普通字符包括沒有顯式指定為元字符的所有可打印和不可打印字符。這包括所有大寫和小寫字母、所有數(shù)字、所有標點符號和一些其他符號。
1.2特殊字符
特殊字符是正則表達式里有特殊含義的字符,也是正則表達式的核心匹配語法。參見下表:
| 特殊字符 | 描述 |
$ | 匹配輸入字符串的末尾位置 |
| * | 匹配前面的子表達零次或多次 |
| + | 匹配前面的子表達零次或多次 |
| [ | 標記一個中括號表達式開始 |
| ? | 匹配前面子表達式零次或一次,或指明非貪婪限定符 |
| \ | 將下一個字符標記為或特殊字符、或原義字符、或向后引用、或八進制轉(zhuǎn)義符。例如,n匹配字符n。\n 匹配換行符。序列\(zhòng)\匹配\字符,而\則匹配‘(·字符。 |
| ~ | 匹配輸人字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。 |
| { | 標記限定符表達式開始 |
| \| | 指明兩項之間的一個選擇 |
補充:
(,)標記一個子表達式的開始和結(jié)束位置,子表達式可以供以后使用
. :匹配前面除\n之外的任何單字符
1.3限定字符
限定符用來指定正則表達式的一個給定的組件必須要出現(xiàn)多少次才能滿足匹配。見下表:
| 字符 | 描述 |
| * | 匹配前面的子表達式零次或多次。例如,foo* 能匹配 fo 以及 foooo。* 等價于 {0,}。 |
| + | 匹配前面的子表達式一次或多次。例如,foo+ 能匹配 foo 以及 foooo,但不能匹配 fo。+ 等價于 {1,}。 |
| ? | 匹配前面的子表達式零次或一次。例如,Your(s)? 可以匹配 Your 或 Yours 中的 Your 。? 等價于 {0,1}。 |
| {n} | n 是一個非負整數(shù)。匹配確定的 n 次。例如,o{2} 不能匹配 for 中的 o,但是能匹配 foo 中的兩個 o。 |
| {n,} | n 是一個非負整數(shù)。至少匹配 n 次。例如,o{2,} 不能匹配 for 中的 o,但能匹配 foooooo 中的所有 o。o{1,} 等價于 o+。o{0,} 則等價于 o*。 |
| {n,m} | m 和 n 均為非負整數(shù),其中 n 小于等于 m。最少匹配 n 次且最多匹配 m 次。例如, o{1,3} 將匹配 foooooo 中的前三個 o。o{0,1} 等價于 o?。注意,在逗號和兩個數(shù)之 間不能有空格。 |
2 std::regex極其相關(guān)
2.1regex_match
對字符串內(nèi)容進行匹配的最常見手段就是使用正則表達式??上г趥鹘y(tǒng) C++ 中正則表達式一直沒 有得到語言層面的支持,沒有納入標準庫,而 C++ 作為一門高性能語言,在后臺服務(wù)的開發(fā)中,對 URL 資源鏈接進行判斷時,使用正則表達式也是工業(yè)界最為成熟的普遍做法。
C++11 提供的正則表達式庫操作 std::string 對象,模式 std::regex (本質(zhì)是 std::basic_regex) 進行初始化,通過 std::regex_match 進行匹配,從而產(chǎn)生 std::smatch(本質(zhì)是 std::match_results 對象)。
我們通過一個簡單的例子來簡單介紹這個庫的使用??紤]下面的正則表達式:
[a-z]+\.txt: 在這個正則表達式中, [a-z] 表示匹配一個小寫字母, + 可以使前面的表達式匹配多 次,因此 [a-z]+ 能夠匹配一個小寫字母組成的字符串。在正則表達式中一個 . 表示匹配任意字 符,而 \. 則表示匹配字符 .,最后的 txt 表示嚴格匹配 txt 則三個字母。因此這個正則表達式的 所要匹配的內(nèi)容就是由純小寫字母組成的文本文件。
std::regex_match 用于匹配字符串和正則表達式,有很多不同的重載形式。最簡單的一個形式就是 傳入 std::string 以及一個 std::regex 進行匹配,當匹配成功時,會返回 true,否則返回 false。例 如:
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string fnames[] = {"foo.txt", "bar.txt", "test", "a0.txt", "AAA.txt"};
// 在 C++ 中 \ 會被作為字符串內(nèi)的轉(zhuǎ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 三個參數(shù),其中 std::smatch 的本質(zhì)其實是 std::match_results。在標準庫中,std::smatch 被定義為了 std::match_results, 也就是一個子串迭代器類型的 match_results。使用 std::smatch 可以方便的對匹配的結(jié)果進行獲取
#include<iostream>
#include<string>
#include<regex>
int main()
{
std::string fnames[] = {"foo.txt", "bar.txt", "test", "a0.txt", "AAA.txt"};
// 在 C++ 中 \ 會被作為字符串內(nèi)的轉(zhuǎ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 的第一個元素匹配整個字符串
// std::smatch 的第二個元素匹配了第一個括號表達
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ī)則的子字符串替換為其他字符串。(會改變字符串本身)
測試代碼 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測試代碼: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檢驗數(shù)字表達式
數(shù)字 : ^[0-9]*$
n 位的數(shù)字 : ^\d{n}$
至少 n 位的數(shù)字 : ^\d{n,}$
m-n 位的數(shù)字 : ^\d{m,n}$
零和非零開頭的數(shù)字 : ^(0|[1-9][0-9]*)$
非零開頭的最多帶兩位小數(shù)的數(shù)字 : ^([1-9][0-9]*)+(.[0-9]{1,2})?$
帶 1~2 位小數(shù)的正數(shù)或負數(shù) : ^(\-)?\d+(\.\d{1,2})?$
正數(shù) , 負數(shù) , 和小數(shù) : ^(\-|\+)?\d+(\.\d+)?$
有兩位小數(shù)的正實數(shù) : ^[0-9]+(.[0-9]{2})?$
有 1~3 位小數(shù)的正實數(shù) : ^[0-9]+(.[0-9]{1,3})?$
非零的正整數(shù) : ^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的負整數(shù) : ^\-[1-9][]0-9″*$ 或 ^-[1-9]\d*$
非負整數(shù) : ^\d+$ 或 ^[1-9]\d*|0$
非正整數(shù) : ^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非負浮點數(shù) : ^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮點數(shù) : ^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮點數(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]*))$
負浮點數(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]*)))$
浮點數(shù) : ^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
3.2檢驗字符串表達式
漢字 : ^[\u4e00-\u9fa5]{0,}$
英文和數(shù)字 : ^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
長度為 3~20 的所有字符 : ^.{3,20}$
由 26 個英文字母組成的字符串 : ^[A-Za-z]+$
由 26 個大寫英文字母組成的字符串 : ^[A-Z]+$
由 26 個小寫英文字母組成的字符串 : ^[a-z]+$
由數(shù)字和 26 個英文字母組成的字符串 : ^[A-Za-z0-9]+$
由數(shù)字 , 26 個英文字母或者下劃線組成的字符串 : ^\w+$ 或 ^\w{3,20}$
中文 , 英文 , 數(shù)字包括下劃線 : ^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文 , 英文 , 數(shù)字但不包括下劃線等符號 : ^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以輸入含有^%&',;=?$\"等字符 : [^%&',;=?$\x22]+
禁止輸入含有 ~ 的字符 : [^~\x22]+
3.3檢驗特殊表達式
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-./?%&=]*)?$
手機號碼 : ^(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}$
電話號碼("XXX-XXXXXXX" , "XXXX-XXXXXXXX" , "XXX-XXXXXXX" , "XXX-XXXXXXXX" , "XXXXXXX"和"XXXXXXXX) : ^($$\d{3,4}-)|\d{3.4}-)?\d{7,8}$
國內(nèi)電話號碼 (0511-4405222 , 021-87888822) : \d{3}-\d{8}|\d{4}-\d{7}
身份證號 (15 位 , 18 位數(shù)字) : ^\d{15}|\d{18}$
短身份證號碼 (數(shù)字 , 字母 x 結(jié)尾) : ^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
帳號是否合法(字母開頭,允許 5~16 字節(jié),允許字母數(shù)字下劃線) : ^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密碼 (以字母開頭,長度在 6~18 之間,只能包含字母 , 數(shù)字和下劃線) : ^[a-zA-Z]\w{5,17}$
強密碼 (必須包含大小寫字母和數(shù)字的組合,不能使用特殊字符,長度在 8~10 之間) : ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式 : ^\d{4}-\d{1,2}-\d{1,2}
一年的 12 個月(01~09和1~12) : ^(0?[1-9]|1[0-2])$
一個月的 31 天(01~09和1~31) : ^((0?[1-9])|((1|2)[0-9])|30|31)$
注意:
在C++中,對于特殊字符,需要使用轉(zhuǎn)義字符. 因此,匹配數(shù)字的\d,需要寫成\d這種格式.
經(jīng)典的三部曲匹配:
1.先寫pattern. string pattern = {“XXXX”};
2.使用re. regex re(pattern);
3.match. bool rs = regex_match(mobile, re);
4.regex_match在匹配一次后即返回結(jié)果,如果期望進行多次匹配,需要用到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)容與正則表達式pattern是對應(yīng)匹配的. 具體可參考matchPriceInfo方法.
總結(jié)
到此這篇關(guān)于c++正則表達式的文章就介紹到這了,更多相關(guān)c++正則表達式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解C++編程中多級派生時的構(gòu)造函數(shù)和訪問屬性
這篇文章主要介紹了詳解C++編程中多級派生時的構(gòu)造函數(shù)和訪問屬性,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-09-09
C++中opencv4.1.0環(huán)境配置的詳細過程
Mingw64編譯wxWidgets 3.0.2常見錯誤分析

