熱線電話:0755-23712116
郵箱:contact@shuangyi-tech.com
地址:深圳市寶安區(qū)沙井街道后亭茅洲山工業(yè)園工業(yè)大廈全至科技創(chuàng)新園科創(chuàng)大廈2層2A
正則表達式是一組由字母和符號組成的特殊文本, 當你想要判斷許多字符串是否符合某個特定格式;當你想在一大段文本中查找出所有的日期和時間;當你想要修改大量日志中所有的時間格式,在這些情況下,正則表達式都能幫上忙。
簡單來說,正則表達式描述了一系列規(guī)則,通過這些規(guī)則,可以在字符串中找到相關的內(nèi)容,規(guī)則使得搜索的能力更加強大。匹配的過程由正則表達式引擎完成。開發(fā)者通常不需要關心正則表達式引擎的實現(xiàn)細節(jié),直接使用其提供的能力即可。
大家可以先想象你正在寫一個應用, 然后你想設定一個用戶命名的規(guī)則, 讓用戶名包含字符,數(shù)字,下劃線和連字符,以及限制字符的個數(shù),好讓名字看起來沒那么丑. 我們使用以下正則表達式來驗證一個用戶名:
以上的正則表達式可以接受 john_doe , john12_as . 但不匹配 Jo , 因為它包含了大寫的字母而且太短了.
本文將以C++語言為例,介紹其中的正則表達式相關知識。
C++中正則表達式的API基本上都位于
部分代碼為了簡化書寫,都已經(jīng)默認做了以下操作:
為了使大家有一個直觀的感受,文章的開頭先通過一些入門示例給大家一個直觀的感受。在這個基礎之上,再詳細講解其中的細節(jié)。
使用正則表達式的大致流程如下:首先你有一段需要處理的文本。這可能是一個字符串對象,也可能是一個文本文件,或者是一大堆日志。接下來你會有特定的目標,例如:找出文本中所有的時間和日期。這個時候你就需要根據(jù)可能的格式寫出具體的正則表達式,例如,日期的格式是:2020-01-01,那么你的正則表達式可能是這樣:。(你現(xiàn)在不必糾結(jié)與這個正則表達式是什么意思,因為這是本文接下來要講解的內(nèi)容。)
有了正則表達式之后,你需要將你的文本和正則表達式交給正則表達式引擎 – 由C++語言(或者其他語言)提供。引擎會在文本中搜索到匹配的結(jié)果。這個結(jié)果的格式可能是包含了多個組,例如:你可能需要分離出年份和月份。有了引擎返回的結(jié)果之后,你就可以進一步處理了。
使用正則表達式的流程大體都是一致的,下面是最常見(其他形式大多為其變種)的三種使用方式。
匹配是判斷給定的字符串是否符合某個正則表達式。例如:你想判斷當前文本是否全部由數(shù)字構(gòu)成。
下面是一段代碼示例:
在這段代碼中:
判斷第一個字符串是否匹配,這里將返回false
判斷第二個字符串是否匹配,這里將返回true這段代碼輸出如下:
還有一些時候,我們要判斷的并非是文本的全體是否匹配。而是在一大段文本中搜索匹配的目標。
下面是一段代碼示例,這段示例演示了在一個字符串中查找數(shù)字:
來保存匹配的結(jié)果。除了
,還有
也很常用。前者是以
的形式返回結(jié)果,后者是以
的形式返回結(jié)果。
函數(shù)搜索結(jié)果這段代碼輸出如下:
最后,使用正則表達式的還有一個常見功能是文本替換。很多的編輯器都有這樣的功能。
例如,下圖是我的Visual Studio編譯器,在搜索替換文本的時候,可以使用正則表達式,這時搜索的能力就更加強大了?!癋ind:”部分可以通過正則表達式來描述待替換的字符串,“Replace:”部分填寫替換的字符串。
下面是在C++中使用正則表達式完成字符串替換的代碼示例:
完成替換
輸出結(jié)果最終輸出的字符串如下:
通過上面的三個示例我們看到,,
和
三個函數(shù)是正則表達式的核心,它們會運行正則表達式引擎完成匹配,查找和替換任務。
C++中內(nèi)置了多種正則表達式文法,在創(chuàng)建正則表達式的時候可以通過參數(shù)來選擇。
不同的文法在表達上有一些不同,如果你原先已經(jīng)很熟悉或者
文法的正則表達式,你可以直接使用它們。對于其他人來說,我們直接使用默認的ECMAScript文法即可(
的正則表達式也是使用ECMAScript文法)。
C++ 中的 ECMAScript 正則表達式文法是 ECMA-262 文法,你可以點擊鏈接查看詳細內(nèi)容。
在代碼中寫字符串有時候是比較麻煩的,因為很多字符需要通過反斜杠轉(zhuǎn)義。當有多個反斜杠連在一起時,就很容易寫錯或者理解錯了。
當通過字符串來寫正則表達式時,這個問題就更嚴重了。因為正則表達式本身也有一些字符需要轉(zhuǎn)義。例如,對于這樣一個字符串 大部分人恐怕很難一眼看出其含義了。
在正則表達式很復雜的時候,推薦大家使用來表達。這種表達式是告訴編譯器:這里的內(nèi)容是純字符串,因此不再需要增加反斜杠來轉(zhuǎn)義特殊字符。
Raw string literal 的格式如下:
這其中:
也就是說,中的
是你需要的字符串本身。
下面是一個代碼示例:
它將輸出:
可以看到,這里的雙引號和反斜杠不會被解釋成轉(zhuǎn)義字符,而是當成字符串內(nèi)容本身,因此會原樣輸出。這樣就減少了轉(zhuǎn)義字符的復雜度,于是更容易理解了。
正則表達式本身定義了一些特殊的字符,這些字符有著特殊的含義。它們?nèi)缦卤硭尽?/p>
這些字符并不少,剛開始接觸可能記不住,但隨著下文的講解,相信你會逐漸熟悉它們。
字符類,顧名思義:是對字符的分類。
例如:1234567890這些都屬于數(shù)字字符類。除此之外,還有其他的分類,它們?nèi)缦卤硭荆?/p>
這里我們可以看到:
作為標識,因此這兩個字符是正則表達式的中的特殊字符。如果是想使用這兩個字符本身,需要對它們進行轉(zhuǎn)義。
內(nèi)部,通過
來描述字符類的名稱。
中可以通過
表示否定,即:字符類的反面。接下來我們看一個代碼示例:
這段代碼稍微有些長,但還是比較好理解的。
該程序的輸出如下:
請仔細看一下這個輸出,并確認與你的認知是否一致。這里的有些字符類包含了換行符,因此在輸出的結(jié)果中也是換行的。
上面的示例中,我們一次只匹配了一個字符。這樣做效率是很低的。
在很多時候,我們當然是想一次性匹配出一個完整的字符串。例如:一個手機號碼。這種情況下,其實是多個數(shù)字字符的重復。
下面就是在正則表達式中描述重復的方式。它們通常跟在字符類的后面,描述該字符出現(xiàn)多次。
知道重復的方法之后,正則表達式的查找能力就更強大了。看一下下面這個代碼示例:
在這段代碼中:
match_result
用來存儲查找的結(jié)果。regex_search
在字符串中查找匹配字符。[[:alnum:]]{5}
是指:字符或者數(shù)字出現(xiàn)5次。\\w{5,}
是指:字母,數(shù)字或者下劃線出現(xiàn)5次或更多次。R"(\W{3,5})"
是指:非字母,數(shù)字或者下劃線出現(xiàn)3次到5次。[[:digit:]]*
是指:數(shù)字出現(xiàn)任意多次。.+
是指:任意字符出現(xiàn)至少1次。[[:lower:]]?
是指:小寫字母出現(xiàn)0次或者1次。該程序輸出如下: