C++與正規表示式入門 - IT人
文章推薦指數: 80 %
C++中正規表示式的API基本上都位於
部分程式碼為了簡化書寫,都已經預設做了以下操作: #include
簡單來說,正規表示式描述了一系列規則,通過這些規則,可以在字串中找到相關的內容,規則使得搜尋的能力更加強大。
匹配的過程由正規表示式引擎完成。
開發者通常不需要關心正規表示式引擎的實現細節,直接使用其提供的能力即可。
大家可以先想象你正在寫一個應用,然後你想設定一個使用者命名的規則,讓使用者名稱包含字元,數字,下劃線和連字元,以及限制字元的個數,好讓名字看起來沒那麼醜.我們使用以下正規表示式來驗證一個使用者名稱:
以上的正規表示式可以接受john_doe,john12_as.但不匹配Jo,因為它包含了大寫的字母而且太短了.
本文將以C++語言為例,介紹其中的正規表示式相關知識。
C++中正規表示式的API基本上都位於
部分程式碼為了簡化書寫,都已經預設做了以下操作:
#include
在這個基礎之上,再詳細講解其中的細節。
使用正規表示式的大致流程如下:首先你有一段需要處理的文字。
這可能是一個字串物件,也可能是一個文字檔案,或者是一大堆日誌。
接下來你會有特定的目標,例如:找出文字中所有的時間和日期。
這個時候你就需要根據可能的格式寫出具體的正規表示式,例如,日期的格式是:2020-01-01,那麼你的正規表示式可能是這樣:\d{4}-\d{2}-\d{2}。
(你現在不必糾結與這個正規表示式是什麼意思,因為這是本文接下來要講解的內容。
)
有了正規表示式之後,你需要將你的文字和正規表示式交給正規表示式引擎–由C++語言(或者其他語言)提供。
引擎會在文字中搜尋到匹配的結果。
這個結果的格式可能是包含了多個組,例如:你可能需要分離出年份和月份。
有了引擎返回的結果之後,你就可以進一步處理了。
使用正規表示式的流程大體都是一致的,下面是最常見(其他形式大多為其變種)的三種使用方式。
匹配
匹配是判斷給定的字串是否符合某個正規表示式。
例如:你想判斷當前文字是否全部由數字構成。
下面是一段程式碼示例:
strings1="ab123cdef";//①
strings2="123456789";//②
regexex("\\d+");//③
cout<
而迭代器正好滿足這一需求,它會依次返回它從文字中找到的匹配內容。
示例:統計出文字中一共出現了多個單詞。
思路:組成單詞的字母可以使用[[:alpha:]]字元類來表達,一個單詞至少有一個字母,因此這個正規表示式可以寫成:[[:alpha:]]+。
然後藉助迭代器便可以統計出總數量。
程式碼示例如下:
#include
它們中與“文法”相關的已經在上文介紹過了。
剩下的還有幾個說明如下:
值
效果
icase
以不考慮大小寫進行字元匹配。
nosubs
進行匹配時,將所有被標記的子表示式exprexpr當做非標記的子表示式?:expr?:expr。
不將匹配儲存於提供的std::regex_match結構中,且mark_count()為零
optimize
指示正規表示式引擎進行更快的匹配,帶有令構造變慢的潛在開銷。
例如這可能表示將非確定FSA轉換為確定FSA。
collate
形如“[a-b]”的字元範圍將對本地環境敏感。
multiline(C++17)
若選擇ECMAScript引擎,則指定^匹配行首,$應該匹配行尾。
這其中,第一個是我們最常用的。
示例:匹配文字中“regularexpression”所有的單複數,並且不區分大小寫。
思路:單詞的首字母有些會大寫,我們可以通過[Rr]來匹配大寫或者小寫的R字母,但實際上,使用icase無疑會更方便。
程式碼示例:
#include
而是需要捕獲匹配結果中的子串。
例如:我們不僅要匹配出日期,還要捕獲日期中的年份,月份等資訊。
這個時候就要使用分組功能。
我們在介紹正規表示式特殊字元的時候,提到過圓括號(和)。
它們的作用就是分組。
當你在正規表示式中配對的使用圓括號時,就會形成一個分組,一個正規表示式中可以包含多個分組。
分組通過編號0,1,2,…來區分。
編號0的分組是匹配的整體,其他編號根據括號的順序來確定。
這些分組最終可以在匹配完成之後,可以通過std::match_results的API來獲取。
這些API如下表所示:
API
說明
empty
檢查匹配是否成功
size
返回完成建立的結果狀態中的匹配數
max_size
返回子匹配的最大可能數量
length
返回特定分組的長度
position
分會特定分組首字元的位置
str
返回特定分組的字元序列
operation[]
返回指定的分組
prefix
返回目標序列起始和完整匹配起始之間的分組
suffix
返回完整匹配結果和目標序列結尾之間的分組
在C++中,分組叫做子匹配(sub_match)。
std::sub_match這個型別只有一個預設建構函式,通常你不會主動建立它,而是使用std::match_results的介面來獲取它的物件。
示例:查詢出文字中所有的年代,並分離出世紀的部分和年份的部分。
思路:年代的格式是四位數字加上“s”作為字尾。
我們可以通過分組的形式分離出兩個部分。
圖示如下:
程式碼示例:
#include
延伸文章資訊
- 1規則運算式(C++)
本文內容. 正則運算式文法; 文法摘要; 語意詳細資料; 比對和搜尋; 格式旗標; 另請參閱. C++ 標準程式庫支援多個正則運算式文法。 本主題討論使用正則 ...
- 2C++11 嘴砲:Regular Expression 正規表示式
匹配你要的字串(regex_search, regex_match). 看個例子我相信大家就會懂了:. regex_search_match.cpp. #include <regex> ...
- 3Regular Expression Basics in C++ - Linux Hint
Commonly used functions for C++ regular expressions, are: regex_search(), regex_match() and regex...
- 4Regular expressions library - cppreference.com
Regular expressions library · Target sequence. The character sequence that is searched for a patt...
- 5C++與正規表示式入門 - IT人
C++中正規表示式的API基本上都位於<regex>標頭檔案中。 部分程式碼為了簡化書寫,都已經預設做了以下操作: #include <iostream> ...