美文网首页程序员
Lua string patterns

Lua string patterns

作者: AlbertS | 来源:发表于2016-08-21 19:47 被阅读425次
匹配夏日模式.png

前言#

今天是我每天一篇技术总结计划的第60天,也就是说我坚持每天一篇技术总结已经整整两个月了,我先给自己点个赞。今天也正好是lua函数中string家族里讲解完结的一章,在这一段时间中我们经常会在章节中听到模式匹配这个词,这也是string库函数的强大之处。

Lua并不使用POSIX规范的正则表达式来进行模式匹配。主要的原因出于程序大小方面的考虑:实现一个典型的符合POSIX标准的regexp大概需要4000行代码,这比整个Lua标准库加在一起都大。权衡之下,Lua中的模式匹配的实现只用了500行代码,当然这意味着不可能实现POSIX所规范的所有功能。但是Lua中的模式匹配功能也是很强大的,并且包含了一些使用标准POSIX模式匹配不容易实现的功能。

前面几章一直跟大家说会总结一下模式匹配这一块的内容,今天是周末我就利用多一点时间,根据lua官方文档中关于模式的介绍为主线,我们一起来总结一下lua中关于模式匹配的内容,其中大部分内容官方文档已经介绍过了,我就是翻译一下,可能有理解不正确的地方,欢迎大家批评指正。

内容#


string patterns##


1.Character Class
一个字符类可以被用于表示一组字符,以下组合被允许来来描述一个字符类:

  • x :表示字符x本身(这里的x表示不是魔法字符^$()%.[]*+-?中的一个)。
  • . :表示所有字符(一个点/英文中句号)。
  • %a:表示所有字母。
  • %c:表示所有控制字符。
  • %d:表示所有十进制数字。
  • %l:表示所有小写字母。
  • %p:表示所有标点符号。
  • %s:表示所有空白字符。
  • %u:表示所有大写字母。
  • %w:表示所有字母和数字。
  • %x:表示所有十六进制数。
  • %z:表示0值字符。
  • %x:表示字符x(此处的字符x不是字母或数字)。这是讲魔术字符转义的标准方式,当被用于在模式中表示自身时,任何标点符号(甚至非魔术的)都能加一个前缀%
  • [set]:表示set中的所有字符的联合构成的分类。通过用-分隔截止字符可以指定某个范围的字符。上面描述的所有种类的%x都可用作set的组成部分。set中的所有其他字符表示它们自身。例如[%w_](或[_%w])表示所有字母数字字符和下划线,[0-7]表示八进制数字,[0-7%l%-]表示八进制数字和小写字母以及-字符。
  • [^set]:表示set的补集,其中的set在上面解释了。
  • 字符范围和字符类之间的相互作用是未定义的。因此类似[%a-z]或[a-%%]的模式没有意义。
  • 对于所有单字母表示的字符类(%a%c等等),相应的大写字母表示该字符类的补集。例如,%S表示所有非空白符。
  • 字母、空白和其他字符组合的定义依赖于当前locale。特别地,字符类[a-z]可能不等于%l。

2.Pattern Item
一个模式选项可以是:

  • 一个单个字符类,它匹配该类中的任意单个字符。
  • 一个后跟*的单个字符类,它匹配该类中的0或多个字符。这些重复项将总是匹配最长的可能序列。
  • 一个后跟+的单个字符类,它匹配该类中的1或多个字符。这些重复项将总是匹配最长的可能序列。
  • 一个后跟-的单个字符类,它也匹配该类中的0或多个字符。与*不同,这些重复项将总是匹配最短的可能序列。
  • 一个后跟?的单个字符类,它匹配出现0或1次该类中的字符。
  • %n中的n在1和9之间,这种项匹配一个等价于捕获的字符串的第n个子串(见下面)
  • %bxy中x和y是两个不同的字符;这种项匹配始于x终于y的字符串,并且xy是对称的。这表示,如果一个人从左到右读字符串,对x计数为+1,对y计数为-1,结尾的y是第一个遇到计数为0的y。例如,项%b()匹配带有平衡的圆括号的表达式。

3.Pattern

模式是一系列的模式项。在模式开头的^将匹配固定在源串的开头。在模式结尾的$将匹配固定在源串的结尾。在其他位置上,^$没有特殊含义,表示它们自身。


4.Captures

模式可以含有括在圆括号内的子模式,它们描述捕获。当成功进行一个匹配,源串中匹配捕获的子串被存储(捕获)以便将来使用。捕获根据它们的左圆括号进行编号。例如,在模式"(a*(.)%w(%s*))"中,字符串的匹配"a*(.)%w(%s*)"的部分作为第一个捕获被存储(因此被编号为1),匹配"."的字符被捕获并编号为2,匹配"%s*"的部分被编号为3。

作为一种特殊情况,空捕获()捕获当前字符串位置(一个数字)。例如,如果我们把模式()aa()用于字符串"flaaap",将有两个捕获:3和5。

模式不能含有内嵌的0(即'\0')。使用%z代替。


usage##

  • 首先我们新建一个文件将文件命名为patterntest.lua然后编写代码如下:
-- 这是一个原串
local sourcestr = "ehrt999wj=--=-*-/4mdqwl\0ds123tfef"
print("\nsourcestr = "..string.format("%q",sourcestr));

-- '%z'的使用
local match_ret = string.match(sourcestr, "%z")
print("\n%z match_ret is ", string.format("%q",match_ret))

-- '*'的使用
match_ret = string.match(sourcestr, "%a*")
print("\n%a* match_ret is ", string.format("%q",match_ret))

-- '-'的使用(其实我有点迷糊)
match_ret = string.match(sourcestr, "%a%d-")
print("\n%a- match_ret is ", string.format("%q",match_ret))

-- '%bxy'的使用
match_ret = string.match(sourcestr, "%bhs")
print("\n%bhs match_ret is ", string.format("%q",match_ret))

-- '()xxx()'的使用
local match_ret1, match_ret2 = string.match(sourcestr, "()t9()")
print("\n()t9() match_ret is ", string.format("%q",match_ret1), 
    string.format("%q",match_ret2))
  • 运行结果
string_pattern.png

总结#

  • 为了测试其中一些字符类的效果,我们使用了函数string.match()这个相对简单的函数,可以说明问题就行了。
  • 在代码中我们举了几个不太好理解的例子,比如%z%bxy%a*等,大家可以看一下输出结果感受一下。
  • 在例子中特别是最后一个不太好理解,我的理解是第一个括号输出的索引是捕获字符串的第一个位置,后一个括号输出的是捕获字符串结束的后一个位置。

相关文章

网友评论

    本文标题:Lua string patterns

    本文链接:https://www.haomeiwen.com/subject/gdlisttx.html