字符串模式

Time:5 分钟

String Pattern(字符串模式)由多个字符组成,用于在字符串中寻找特定句段(这些句段通常被称为 Substring,也就是子字符串)。Lua 语言中存在数个能与字符串模式共同使用的字符串函数

直接匹配

只要匹配字符非 Lua 语言中的特殊字符(Magic Character),即可通过在 Lua 函数(例:string.match())中使用该字符串来对其进行直接匹配。举例来说,下列指令将会在字符串中查找 Roblox 一词,并输出匹配结果:

    
    print( string.match("Welcome to Roblox!", "Roblox") )
    print( string.match("Welcome to my awesome game!", "Roblox") )
    
    
    Roblox
    nil

由于在第一个字符串中找到了匹配项,因此 Roblox 被输出至控制台,但在第二个字符串中没有找到匹配项,所以输出为 nil

字符类别

在进行高级字符串搜索时字符类别起着关键性作用:当搜索某种_非特定_子串、且该子串的字符属于某种已知的类别时,就需要用到字符类别。在 Lua 中,开发者可以在某一字符串中搜索字母数字空格, 标点符号等。

下列表格展示了 Lua 字符串模式中正式的字符类别:

类别 含义 匹配示例

. 任意字符 32kasGJ1%fTlk?@94

%a 大写字母或者小写字母 aBcDeFgHiJkLmNoPqRsTuVwXyZ

%l 小写字母 abcdefghijklmnopqrstuvwxyz

%u 大写字母 ABCDEFGHIJKLMNOPQRSTUVWXYZ

%d 任意数字 0123456789

%p 任意标点符号字符 !@#;,.

%w 含有字母或者数字的字符(字母或者数字皆可) aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789

%s 空格或者空白字符 _, \n, and \r

%c 特殊控制字符

%x 十六进制字符 0123456789ABCDEF

%z NULL 字符(\0

%bxy 平衡捕捉,匹配xy 及两者间的所有内容(举例来说,%b()可以捕捉一对圆括号和圆括号内包含的所有内容) (我在圆括号内!)

对于 %a%s 等单字母字符类别来说,当将其字母改换为大写后,将会代表与当前“截然相反”的字符类别。举例来说,%p 代表标点符号字符,而其大写形式 %P则代表着_除了_标点符号之外的所有字符。

Magic Character(特殊字符)

字符串模式中共保留了 12 个“特殊字符”,各自有其专门的用处:

$ % ^ * ( )

. [ ] + - ?

开发者将无法在字符串模式中对这些特殊字符进行直接搜索。举例来说,当需要搜索 . (半角句号)时,不能直接用 "." 作为搜索字符串模式:

string.match("String ending with period.", ".")  -- "." 是字符串模式

若想对保留特殊字符进行直接搜索时,需要在 . (或者其他任何特殊字符)前添加 % 符号(例:%.)。经过此操作后,Lua 即可对特殊字符本身进行搜索。

string.match("String ending with period.", "%.")  -- "%." 是字符串模式

Quantifier(量词)

单独使用时一个字符类别时,只会与字符串中的单个字符进行匹配。举例来说,下列字符串模式("%d")将会从左到右读取字符串,但在找到_第一个_数字(2)时就会停止搜索!

    
    print( string.match("The Cloud Kingdom has 25 power gems", "%d") )
    
    
    2

为了克服这一问题,开发者可以在任意字符类别后面添加一个量词标记,籍此匹配到指定数目的该类别字符。

量词 含义

+ 为前置字符类别匹配 1 个或更多结果

- 为前置字符类别匹配尽可能少的结果

* 为前置字符类别匹配 0 个或更多结果

? 为前置字符类别匹配 1 个或更少结果

字符类别集合

当单一的字符类别没有办法满足复杂匹配需求的时候,开发者应当考虑使用集合(Set)。举例来说,当开发者需要使用单个字符串模式同时对小写字母(%l)和标点符号(%p)进行匹配时,就需要使用集合达成此目的。

集合的定义由方括号([])进行。在下列示例中,请仔细观察使用集合("[%l%p]+")和没有使用集合("%l%p+")时导致的结果差异。

    
    print( string.match("Hello!!! I am another string.", "[%l%p]+") )  -- 集合
    print( string.match("Hello!!! I am another string.", "%l%p+") )    -- 非集合
    
    
    ello!!!
    o!!!

第一条指令(使用集合)中,Lua 将会对小写字母字符与标点符号字符同时进行搜索。同时因为在整个集合后添加了 + 量词,Lua 将会找到所有符合条件的字符(ello!!!),直到其到达空格时停止。

第二条指令(不使用集合)中,+ 量词仅对其前置类别 %p 有效。因此 Lua 会在匹配到第一个小写字母字符(o)后停止对小写字母的匹配,转而开始对标点符号类字符(!!!)进行匹配。

和字符类别一样,开发者也可以通过[的后面(也就是集合本体的最前端)添加 ^ 字符来表达与当前集合完全“相反”的集合类别。举例来说,"[%p%s]+" 集合代表标点符号和空格两种字符,而 "[^%p%s]+" 则代表_除了_标点符号和空格以外的所有字符。

除此之外,集合还支持范围匹配,开发者可以在开始和结束字符之间的一整段范围内寻找符合匹配条件的字符。若希望对此高级匹配功能进行进一步了解,请参见此处

字符串捕获

开发者可以通过 String Capture(字符串捕获)对特定的字符串片段进行获取,并将其保存在变量中:从单独字符类别到多字符类别(带有量词的类别),甚至是字符类别集合都可以通过此功能进行获取。

捕获内容由其两侧的圆括号 () 进行定义。请参见下列示例:

    
    local pattern = "(%a+)%s?=%s?(%d+)"
    
    local key1, val1 = string.match( "TwentyOne = 21", pattern)
    print(key1, val1)
    
    local key2, val2 = string.match( "TwoThousand= 2000", pattern)
    print(key2, val2)
    
    local key3, val3 = string.match( "OneMillion=1000000", pattern)
    print(key3, val3)
    
    
    TwentyOne 21
    TwoThousand 2000
    OneMillion 1000000

请注意上述模式中添加在两个 %s 类别后面的 ? 量词:其对示例中 = 符号任意一侧的空格都进行了非必要化,是极为值得参考的操作。进行该操作后,即使等号任意一侧(或两侧)的空格都出现缺失,匹配也将完全不受干扰!

***Roblox官方链接:字符串模式