Regular Expression

正規表示式

Regular Expression……?

電腦比對字串是否符合規定

e.g.

regex使用環境

  • C++ 11

#include <regex>

  • 宣告正規表示式
  • 常用符號
#include <regex>

int main(){
	std::regex 名稱("格式填入");
	
	return 0;
}

字元類

舉例 其他表示方式 說明
\w [_[:alnum:]],
[A-Za-z0-9_]
數字、字母、底線
\W [^_[:alnum:]],
[^A-Za-z0-9_]
非數字、字母、底線
\d [[:digit:]],
[0-9]
數字
\D [^[:digit:]],
[^0-9]
非數字
\s [[:space:]] 空白字元(包含\n, \t, \r, \f)
\S [^[:space:]] 非空白字元

特殊字元

舉例 說明
. 任何字元
[     ] 含括字元類
{     } 含括重複次數
^ 否定;以…開始
$ 以…結束

出現次數

舉例 說明
{n} 出現n次
{n,} 出現n次以上
{n,m} 出現n到m次
特殊重複字元 等效表示法
* {0,}
+ {1,}
? {0,1}

What can regular expression do?

  • 匹配 regex_match
  • 搜尋 regex_search
  • 替換 regex_replace

regex_match(字串, 正規表示式)

#include <iostream>
#include <regex>
using namespace std;
int main(){
	string s1 = "!@#$"; // 宣告一個沒有字母、數字、底線的字串
	string s2 = "12ab_"; // 宣告一個有字母、數字、底線的字串
	regex ex("\\w*"); // 宣告正規表示式
	cout << s1 << " is all _[:alnum:]: " << regex_match(s1, ex) << endl; // 符合輸出1
	cout << s2 << " is all _[:alnum:]: " << regex_match(s2, ex) << endl; // 不符合輸出0
	return 0;
}

匹配字串是否符合格式

regex_search(字串, 儲存結果, 正規表示式)

#include <iostream>
#include <regex>
using namespace std;
int main(){
	string s = "ab123cdef"; // 字串
	regex ex("\\d+");    // 正規表示式
	smatch match; // 儲存結果容器
	regex_search(s, match, ex); // 執行搜尋函式
	cout << s << " contains digit: " << match[0] << endl; // 輸出結果
	return 0;
}

搜尋符合格式的字串

搜尋字串:smatch

搜尋字元陣列:cmatch

regex_replace(字串, 正規表示式, 替代字串)

#include <iostream>
#include <regex>
using namespace std;
int main(){
	string s = "ab123cdef"; // 字串
	regex ex("\\d+");    // 正規表示式
	cout << regex_replace(s, ex, "xxx") << endl; // 輸出替換數字的結果
	return 0;
}

修改符合格式的字串

Practice

小資要統整大家的出生年月日。為了使資料整齊,他想規定大家以xxxx-xx-xx的方式(e.g. 2000-01-01)。

請幫小資寫一個程式。若輸入符合格式,則輸出「Thank you.」;不符合格式,則輸出「Please follow the format.」

寫好程式後,請自行輸入三筆測試資料,並截圖執行的結果放到fb。

輸入 輸出
2004-10-26 Thank you.
2005/04/25 Please follow the format.
2005-7-19 Please follow the format.

Reference Answer

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

int main(){
    std::string ipt;
	std::cin >> ipt;
	std::regex form("\\d{4}-\\d{2}-\\d{2}");
	
	if(std::regex_match(ipt, form)){
	    std::cout << "Thank you.";
	}else{
	    std::cout << "Please follow the format.";
	}
	
	return 0;
}

補充:iterator and regular expression

正規表示式的迭代器

A regular expression, regex or regexp ((sometimes called a rational expression)) is a sequence of characters that define a search pattern. Usually such patterns are used by string searching algorithms for “find” or “find and replace” operations on strings, or for input validation. It is a technique developed in theoretical computer science and formal language theory.

這裡有一篇文章(請不要在意它到底寫了什麼٩(●˙▿˙●)۶…⋆ฺ),

想要統計字數的話,可以怎麼做呢?

我們可以先思考:

1. 單字由字母組成,所以正規表示式應該選用[^\\s]

2. 一個單字會有一個以上的字母,所以應該用+

總結:正規表示式應該為"[^\\s]+"

程式講解

#include <regex>
#include <iterator> //引入迭代器
#include <iostream>
#include <string>

int main() {
    std::regex word_regex("[^\\s]+"); //剛剛討論過的正規表示式
    std::string line;
    getline(std::cin, line); //輸入含有空白的字串
    
    auto iter_begin = std::sregex_iterator(line.begin(), line.end(), word_regex);//通過正規表示式迭代器從文字行的逐一匹配
    auto iter_end = std::sregex_iterator(); 
    
    std::cout << "It contains " << std::distance(iter_begin, iter_end)  << " words"; //輸出字數
    return 0;
}

附錄:other character classification

其它字元類

字元類 說明
[[:alpha:]] 任意字母
[[:blank:]] 非換行的空白字元
[[:cntrl:]] 控制字元
[[:graph:]] 圖形字元
​[[:lower:]] 小寫字母
[[:print:]] ​可列印字元
​[[:punct:]] ​標點符號
​[[:upper:]] ​大寫字母
[[:xdigit:]] 十六進位制的數字字元

deck

By alice11135917