置顶公告:【置顶】关于临时开启评论区所有功能的公告(2022.10.22) | 【置顶】关于本站Widget恢复使用的公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

用戶:東東君/正則表達式

萌娘百科,萬物皆可萌的百科全書!轉載請標註來源頁面的網頁連結,並聲明引自萌娘百科。內容不可商用。
跳至導覽 跳至搜尋

簡介

正則表達式(英語: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?這種形式。
  • 不支持任何零寬斷言,如:?= 、 ?<= 、 ?! 、 ?<!