用戶:東東君/正則表達式
簡介
正則表達式(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),是計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。在很多文本編輯器里及程序中,正則表達式通常被用來檢索、替換那些匹配某個模式的文本。
wikitext語法中沒有「數據類型」這一概念,我們可以認為其中的所有數據都是字符串(string)類型的[來源請求],因此正則表達式可以在wikitext中發揮極大的作用。
因為萌百中對於正則匹配的支持主要基於Lua語言所提供的string庫,string庫的正則表達式實現並未遵照POSIX規範,在使用上會與普通的正則表達式有所不同,這裏着重講解Lua的正則表達式寫法,若你有正則表達式的基礎,也可以先看這裏→Lua正則與標準正則的不同。
語法對照表
Lua中的正則表達式 正則表達式由元字符按照規則(語法)組成。lua中的特殊字符是% . [ ] ( ) ^ $ * + - ?
,一共12個。它們和一般字符按規則構成了lua的正則表達式。
建議先閱讀一遍該表,再結合下面的例子進行理解。
元字符 | 描述 | 表達式示例 | 完整的匹配字符串 |
---|---|---|---|
字符 | |||
普通字符 | 除去%.[]()^$*+-?的字符,匹配字符本身 | string | string |
. | 匹配任意字符 | str.ng | string |
% | 轉義字符,改變後一個字符的原有意思。當後面的接的是特殊字符時,將還原特殊字符的原意。%和一些特定的字母組合構成了lua的預定義字符集。%和數字1~9組合表示之前捕獲的分組 | strin%a | string |
[...] | 字符集(字符類)。匹配一個包含於集合內的字符。[...]中的特殊字符將還原其原意,但有下面幾種特殊情況 1. %],%-,%^作為整體表示字符']','-','^' 2. 預定義字符集作為一個整體表示對應字符集 3. 當]位於序列的第一個字符時只表示字符']' 4. 形如[^...],[...-...]有特定的其他含義 |
strin[a-z] | string |
* | 表示前一個字符出現0次或多次 | s* | sssss |
+ | 表示前一個字符出現1次或1次以上 | s+tring | ssstring |
- | 表示前一個字符出現0次或多次,且將儘可能匹配較少的內容 | s-tring | tring |
? | 表示前一個字符出現0次或1次 | strin?g | strig |
預定義字符集 | |||
%s | 空白字符[ \r\n\t\v\f](半角空格、全形空格、換行) | str%sing | str ing |
%p | 半角標點符號 | str%ping | str,ing |
%c | 控制字符 | ||
%w | 字母數字,相當於[a-zA-Z0-9] | %w%w%w | st0 |
%a | 字母a到z和A-Z,相當於[a-zA-Z] | %a%a%a | str |
%l | 小寫字母,相當於[a-z] | %l%l%l | str |
%u | 大寫字母,相當於[A-Z] | %u%u%u | STR |
%d | 數字,相當於[0-9] | %d%d%d | 123 |
%x | 16進制數,相當於[0-9a-fA-F] | %x%x%x | 59c |
%z | ascii碼是0的字符 | ||
捕獲組 | |||
(...) | 表達式中用小括號包圍的子字符串為一個分組,分組從左到右(以左括號的位置),組序號從1開始遞增。 捕獲組不會對匹配結果產生任何影響,只是用來在匹配後對匹配結果進行其他操作的 |
(string) | string |
邊界匹配 | |||
^ | 匹配字符串開頭 | ^string | string |
$ | 匹配字符串結尾 | string$ | string |
平衡匹配 | |||
%bxy | 平衡匹配(匹配xy對)。這裏的x,y可以是任何字符,即使是特殊字符也是原來的含義,匹配到的子串以x開始,以y結束,並且如果從x開始,每遇到x,計算+1,遇到y計數-1,則結束的y是第一個y使得計數等於0。就是匹配成對的符號,常見的如%b()匹配成對的括號 | %b{} | {string} |
示例
在這裏我們使用用途最為廣泛的replace(替換匹配)進行演示。
{{#invoke:String|replace |source= <!-- 要匹配的字符串 --> |pattern= <!-- 正则表达式 --> |replace= <!-- 要替换的内容 --> |count= <!-- 替换次数,默认为尽可能地多次匹配 --> }}
該模板未匹配的部分將原封不動地返回,若整個字符串都不匹配,則全部原樣返回。
關於這個模塊的更多細節請參考:User:宇文天啟/字符串處理#replace
捕獲組的使用
{{#invoke:String|replace |source= 卡布奇诺,咖啡摩卡,咖啡拿铁 |pattern= (卡布奇诺),(咖啡摩卡),(咖啡拿铁) <!-- 在正则中使用括号作为捕获组的标志,捕获组本身不会对匹配造成任何影响 --> |replace= %3,%2,%1!魔法少女智乃华丽变身~! <!-- 在替换栏中,使用%n为替代字符,代表对应的捕获组,从1开始,最多9个。若要输出%元字符,则要写成“%%” --> |plain=false <!-- 接上↑:其中,“%0”代表匹配到的全部字符。 --> }}
結果:咖啡拿鐵,咖啡摩卡,卡布奇諾!魔法少女智乃華麗變身~!
匹配任意數量的字符
{{#invoke:String|replace |source= 这是一个超超超超超级厉害的页面! |pattern= .+超+(.+) <!-- 匹配到了整句 --> |replace= %1 <!-- 将匹配到的内容替换为第一个捕获组的内容 --> |plain=false }}
結果:級厲害的頁面!
{{#invoke:String|replace |source= goooooogle |pattern= %l([^g]*)gle <!-- 这里表示[^g]匹配非g的字符 --> |replace= %1 |plain=false }}
結果:oooooo
匹配任意位置的字符
{{#invoke:String|replace |source= 《你好,世界!》123《你好,世界!》 |pattern= 《你好,世界!》(123)$ <!-- 这将原封不动地返回,因为匹配的字符串的末尾不是123 --> |replace= %1 |plain=false }}
結果:《你好,世界!》123《你好,世界!》
{{#invoke:String|replace |source= <123>456<123><123>456<123><123>456<123><123>456<123> |pattern= (<123>456<123>)<123>456<123>$ <!-- 取倒数第二组“<123>456<123>” --> |replace= 【%1】<123>456<123> |plain=false }}
結果:<123>456<123><123>456<123>【<123>456<123>】<123>456<123>
{{#invoke:String|replace |source= 王木匠饭还没吃完,就径直向工场走去,满脑子想的都是今天早上刚到的木料。别看就是个锯木头的,一块好木,在巧匠手里就像是块璞玉... |pattern= (径直向).+(走去) <!-- 有时为了更精确地匹配某个地方,就需要在两边添加许多原文有的,或者可预见的信息,帮助定位 --> |replace= %1家%2 |plain=false }}
結果:王木匠飯還沒吃完,就徑直向家走去,滿腦子想的都是今天早上剛到的木料。別看就是個鋸木頭的,一塊好木,在巧匠手裏就像是塊璞玉...
轉義的使用
{{#invoke:String|replace |source= 平常的流浪者大叔(60岁),昨天给我发邮件说喜欢[汚れ]的小哥(45岁),我(53岁) |pattern= .+(%[汚れ%]的小哥%(45岁%)).+ <!-- 原文包含“[ ] ( )”等语法使用的符号,需要使用%转义为普通符号,防止被作为语法解析 --> |replace= %1 |plain=false }}
結果:[汚れ]的小哥(45歲)
貪婪模式與非貪婪模式
{{#invoke:String|replace |source= a123a a456a a456a bbbbbbbbbbbbbb |pattern= (a.+a).* <!-- 默认为贪婪模式,这将匹配直到文本最后的a的字符串 --> |replace= %1 |plain=false }}
結果:a123a a456a a456a
{{#invoke:String|replace |source= a123a a456a a456a bbbbbbbbbbbbbb |pattern= (a.-a).* <!-- 使用减号的非贪婪模式,只会匹配到第一组 --> |replace= %1 |plain=false }}
結果:a123a
平衡匹配
{{#invoke:String|replace |source= (待添加)实在是太萌了 |pattern= %b() |replace= 智乃酱 |plain=false }}
結果:智乃醬實在是太萌了
應用模板
請參考:User:宇文天啟/字符串處理
- {{REesc}} 這個模板將對字符串內的所有語法符號進行轉義,經常用於模板輸入的參數要加入正則表達式時,進行轉義操作,防止被錯誤解析為正則語法。
Lua正則與標準正則的不同
- 除上表列舉出特殊字符,其他的均無效(如:%r、%t、%w)等。
- 將特殊字符大寫並不代表匹配非該特殊字符的含義,而是會當作普通字符處理。
.
代表任意字符,包括\n
換行符。char{min,max}
不支持指定字符數量的操作,花括號同樣也只是普通字符。(abc|def|)
不支持預料多種結果的操作,若只想判斷是否存在,且可預見的情況下可以使用a?b?c?
這種形式。- 不支持任何零寬斷言,如:?= 、 ?<= 、 ?! 、 ?<!