2024.11.20 鮮花

xrlong發表於2024-11-20

正規表示式

核心共振

⚡超越一切震懾凡人⚡

⚡帶來終結機械降神⚡

⚡風暴之力充滿全身⚡

⚡最後一擊核心共振⚡

就是首先你需要知道一些元字元,也就是它的語法。

最基本的幾個:

^ $ 分別指定行首和行尾。

[abc] 表示匹配 a,b,c 中的一個,當然長度不限。也有一些符合人類直覺的寫法:[a-o] 表示從 a 到 o 的所有小寫字母,[1-9] [A-X] 也都是對的。

[^abc] 表示匹配除了 a,b,c 中的一個,將 ^ 放到 [] 裡相當於取反。

{a} {a,} {a,b} 分別表示匹配恰好 \(a\) 次,至少 \(a\) 次,\([a,b]\) 次。

. 表示一個任意除回車(\n\r)字元,在某些時候(如 C 中不指定 REG_NEWLINE 時)也會匹配回車。

() 用於劃分單元,將其中的內容作為一個單元匹配,可以用 \x 來引用第 \(x\) 段以獲取的匹配,如 (.)\1 匹配兩個相同字元,在 C++ 中查詢時會先儲存整個的匹配,再將每段分別儲存。

| 就是或,兩邊有一邊成立就匹配。

\b 匹配單詞和空格的邊界,並不匹配字元。

\B \b 取反。

\f \n \r \t \v 就是字面意思,匹配換頁,換行,製表等。

\< \> 分別匹配詞首和詞尾,分隔符不一定是空格。

會了上面的基本就會所有了,下面的大多都是上面的的等價簡略寫法。

? 等價 {0,1}

+ 等價 {1,}

\d 等價 [0-9]

\s 匹配不可見,等價 [\f\n\r\t\v]

\w 匹配包括下劃線在內的所有單詞字元,等價 [0-9A-Za-z_]

\D \S \W 上面那仨的取反。

然後想在 C++ 裡用正規表示式,還要學一點語法。

考慮一下速度,boost 的功能強大但有非常“優秀”的速度,C++ 的速度在匹配不上時較快,匹配上時飛慢,而且查詢也是飛慢,所以這裡建議大家用 C 裡的 regex.h,雖然好像只有 linux 能用。

用法就是首先你要引用 <regex.h> 庫。

一共兩個型別,四個函式:

regex_t:用來存已經編譯好的正規表示式。

int regcomp(regex_t &a,const char *s,int t)a 就是用來存的,s 是需要編譯的表示式,t 是編譯 tag,一共四個,等號後面是它的值:REG_EXTENDED=1 使用更牛的庫,一般是要加的,REG_ICASE=2 設定大小寫不敏感,REG_NEWLINE 如果不加,預設忽略回車,就會導致 ^ $ 只能匹配第一個和最後一個,且 . 能匹配回車,加上了就完全取反,REG_NOSUB 不返回匹配結果,只返回是否成功匹配。

regmatch_t:用來存匹配結果,.rm_so 表示起點,.rm_eo 是終點加一。

int regexec(regex_t &a,const char *s,size_t x,regmatch_t &c,int t):表示用表示式 a 匹配(或者說查詢) sx 是儲存個數,會將正串匹配和 \(x-1\) 前個單元的匹配放到 c,若制定了 REG_NOSUB 會忽略;t 是 tag,一共兩種,REG_NOTBOL=1 表示禁用 ^REG_NOTEOL=2 表示禁用 $,若指定了 REG_NEWLINE 會忽略,返回值為 \(0\) 表示找到了,為其他表示沒找到或出現錯誤;每次只能匹配第一個,要匹配所有的話寫迴圈每次位移即可。

因為 regcomp 分配了記憶體,所以在每次編譯後都要用 void regfree(regex_t &a) 來釋放記憶體。理論上每次重新編譯也要先釋放,但是實測不釋放也能過,不知道會不會有其他問題。

regerror 是在產生錯誤後返回錯誤資訊,感覺沒啥用,可以自行百度。

有個板子:正規表示式

P