• (转)LUA正则表达式不完全指南


    转自剑侠论坛,并稍微修改个别文字。

     好不容易闲下来,研究了一下正则表达式,然后越钻越深,经过跟大神们讨论学习后,就没有然后了。总之╮(╯▽╰)╭很有用的一个东西,至少对于用户输入的读取方面会比较方便,所以就简单举例说说。

    注:正则这个比较不好理解,经常容易转不过弯来,个人觉得最好的学习方式就是自己去试,举一反三,才会知道错在哪里,我尽量提供不同种类同样用法的例子方便理解。

    正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。(好吧,这是百度来的)
    简单来说就是按照一定想法获取与替换字符串。想怎么换就怎么换(真的( ⊙o⊙ )?)

    日常运用的时候,会遇到的情况比如某段话里带有关键字,多个关键字等
    “日常大战xxx来治疗”,“收xxx,带价密”
    这时候捕获这些字符串下来进行分析与记录,让你不至于错过某些不应该错过的,或者说自动密那个人预定位置什么的……嗯,好像扯远了,那是插件,今天只说lua。

    元字符 描述
    .   匹配任意字符,包括中文、字母、数字、符号等
    % 特殊符号转义,例如:%.为匹配点,%%为匹配百分比符号,跟“”用来转义引号是一样的
    %a alphabet,匹配字母,大小写都匹配,%A为匹配除字母外其他字符
    %b bisymmetric,匹配对称字符,%bxy,x为开始匹配字符,y为结束匹配字符,xy可随意指定。例如:%b<>为匹配包括<>在内的所有字符
    %c control character,匹配控制字符,详见百度,%C为匹配除控制字符外其他字符
    %d digit,匹配数字,0到9,%D为匹配除数字外其他字符
    %l lower case,匹配小写字母a-z,%L为匹配小写字母外其他字符
    %p punctuation,匹配标点符号,%P为匹配标点符号外其他字符
    %s space,匹配空白符号,包括 (tab键四格空白), (新行的标示), (换行的标示),%S为匹配空白符号外其他字符
    %u upper case,匹配大写字母A-Z,%U为匹配大写字母外其他字符
    %w words,匹配字母和数字,%W为匹配字母和数字外其他字符
    %x hex,匹配十六进制数字,%X为匹配十六进制数字外其他字符
    %z zero,匹配代表0的字符,%Z为匹配0字符外其他字符
    () 匹配与返回括号内的内容,例如:123(.+),匹配与返回带有123字样后续内容。详见下
    [] 自定义匹配字符集,例如:[a-z0-9,%.]匹配a到z以及0-9还有逗号,百分比号跟点,[^a-z0-9,%.]匹配除字符集以外的其他字符
    + 匹配前一字符1次或多次,常用于连贯性字符,例如:%a+ 以单词为单位匹配
    * 匹配前一字符0次或多次,最长匹配,常用于匹配空白符,例如%s*,将会匹配字符串内所有单个或者连贯空格
    - 匹配前一字符0次或多次,最短匹配,在进行所有字符匹配时匹配最短,例如:|123|456|,用|(.*)|则会返回123|456,而|(.-)|则只返回123 
    ? 匹配前一字符0次或1次,例如:匹配正负数字,因为正数不带负号
    ^ 匹配开头,例如:^%d+为以数字开头的匹配,可与匹配结尾一同使用
    $ 匹配结尾,例如:%d+$为以数字开头的结尾,可与匹配开头一同使用

    常用string操作:
    参考资料:http://www.lua.org/manual/5.1/manual.html

    string.find(s,pattern[,init[,plain]])
    匹配第一个符合条件的项目的起始位置与终止位置,如果没找到则返回nil
    s代表目标字符串
    pattern代表你要匹配的规则,见上面正则表格
    init代表开始匹配的位置,默认为1,可以是负数,可不填
    plain布尔值,如果为true时,则执行匹配任何匹配规则不生效,只是简单的字面匹配

     


    s = "%d+002929aciwe%a+cqoe01230"
    local x,y = string.find(s,"%d+",1) --匹配数字,一次或多次连续
    print(x,y)
    --> x = 4, y = 9
    s = "%d+002929aciwe%a+cqoe01230"
    local x,y = string.find(s,"%d+",10) --匹配数字,一次或多次连续
    print(x,y)
    --> x = 22, y = 26
    s = "%d+002929aciwe%a+cqoe01230"
    local x,y = string.find(s,"%d+",1,true) --匹配字符"%d+"
    print(x,y)
    --> x = 1, y = 3
    s = "%d+002929aciwe%a+cqoe01230"
    local x,y = string.find(s,"%a+",1) --匹配字母,一次或多次连续
    print(x,y)
    --> x = 2, y = 2
    s = "%d+002929aciwe%a+cqoe01230"
    local x,y = string.find(s,"%a+",1,true) --匹配字符"%a+"
    print(x,y)
    --> x = 15, y = 17

     

    string.match(s,pattern[,init])
    匹配第一个符合条件的项目
    s代表目标字符串
    pattern代表你要匹配的规则,见上面正则表格
    init代表开始匹配的位置,默认为1,可以是负数,可不填

     

    s = "1number123xyz"
    x = string.match(s,"%d+",1) --匹配数字,一次或多次匹配,从第一号位开始找
    -->x = 1     --返回值是1
    x = string.match(s,"%d+",2) --匹配数字,一次或多次匹配,从第二号位开始找
    -->x = 123    --返回值是123
    x = string.match(s,"%d+",-4) --匹配数字,一次或多次匹配,从右起第四号位开始向右找
    -->x = 3
    x = string.match(s,"%d+",-3) --匹配数字,一次或多次匹配,从右起第三号位开始向右找
    -->x = nil
    x = string.match(s,"%d*",-3) --匹配数字,零次或多次匹配,从右起第三号位开始向右找
    --> 完成匹配,返回空白

    string.gmatch(s,pattern)
    返回迭代器,每次调用时会返回符合条件的项目和迭代器,如果没有指定条件,返回整个字符串。
    s代表目标字符串
    pattern代表条件

     

    s = "1number123xyz"
    for x in string.gmatch(s,"%d+") do --匹配数字,一次或多次
    print(x)
    end
    --> x = 1, x = 123
    s = "1number123xyz"
    for x in string.gmatch(s,"%d-") do --匹配数字,0次或多次,最短匹配,即0次
    print(x)
    end
    -->完成匹配,返回空白
    s = "1number123xyz"
    for x in string.gmatch(s,"%d*") do --匹配数字,0次或多次,最长匹配
    print(x)
    end
    -->1          123 --中间为空白

    t = {}
    s = "hello=123,         lua=456"
    for k,v in string.gmatch(s,"(%w+)=(%w+)") do --匹配等号两边的数字与字母一次或多次,并且分别返回括号内的两个值
    t[k]=v
    print(k,v)
    end
    --> hello     123
          lua       456
    --> t= {["hello"]="123",["lua"]="456"}

    string.sub(s,i[,j])
    返回一项字符串的一部分
    s为目标字符串
    i为起始位置
    j为终止位置,可不填,默认为-1,即使字串结束
    i,j都可为负数

     

    s = "我们是快乐的人啊!23333"
    local x = string.sub(s,1,-6)
    --> x="我们是快乐的人啊!"


    重点介绍,最常用的
    string.gsub(s,pattern,repl[,n])
    返回因符合规则被全部或替换n次后的字符串,同时返回匹配成功次数
    s为目标字符串
    pattern为规则
    repl为替换字符串,可为string,function,table。如果为string,则%在这里作为一个特殊符号,任何%1到%9代表会第几次的返回值(这个返回值是一次匹配成功值下面会介绍),%1就是第一个值,%9则是第九个。而%0则是全部。而%%则表示百分比字符。如果repl是function,每次匹配成功将会调用函数,会将匹配到的字符串变为参数,如果没有指定规则,则将整个字符串传为一个参数。如果rep是table,则每次匹配成功都会与table进行比对,如符合array则替换为key值,如没有规则,则以整个字符串作为比对。注:如果function和table的返回值是string或者数字,那么则替换,如果返回false或者nil则不进行替换。
    n为执行几次替换

    s="先来最基础简单的"
    x = string.gsub(s,"基础简单","复杂困难") --将"基础简单"替换成"复杂困难"
    --> x = "先来最复杂困难的"
    s="多次替换数字123,多次替换数字321"
    x = string.gsub(s,"%d+","lalala") --将数字替换成"lalala"
    --> x = "多次替换数字lalala,多次替换数字lalala"
    s="本末&倒置,开始=逆转"
    x = string.gsub(s,"(.+)&(.+),(.+)=(.+)","%3%2%4%1") --一次匹配下返回括号内四个值,并且排列后替换整个字符串
    --> x = "开始倒置逆转本末"

    %1-%4相当于临时变量,将临时变量赋予括号内的值并且将整个字符串替换成临时排列后的变量。
    %1 = 本末,%2 = 倒置,%3=开始,%4=逆转,而%0则是等于整个字符串:本末&倒置,开始=逆转

    s="hello string test world"
    x = string.gsub(s,"(%w+)%s*(%w+)","%1",1) --一次匹配返回两个值,将这两个替换成第一个值,只执行一次
    --> x = "hello test world"

    由于(%w+)%s*(%w+) 是匹配两个单词为一对,那么在例子里面符合条件的有两对,一个是hello string以及test world。首先匹配到hello string返回两个值%1=hello,%2=string,然后将整个hello string替换成hello。而由于值执行一次,所以第二对匹配成功的则不进行替换

    s="hello string test world"
    x = string.gsub(s,"(%w+)%s*(%w+)","%0 %0",1) --匹配成功后将多复制一次,只执行一次
    --> x = "hello string hello string test world"

    匹配成功的是hello string,两个%0代表这个hello string会出现两次,也就是这个结果了。

     

    pattern为函数的,如下例:

    function a(s)
    return loadstring(s)()
    end
    x = string.gsub("2+6 = $return 2+6$", "%$(.-)%$",a)
    --> x = "2+6 = 8"

    pattern为table的,如下例:


    local t = {name="lua", version="5.1"}
    x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) --匹配table内的项目并且替换掉原有的
    --> x="lua-5.1.tar.gz"

    说了这么半天,正则主要是看怎么定下规则,其他的应用都听简单的,至于规则的熟悉则要多练习,多实验才能体会到。

    实际范例:
    文本 = 我切,我切|我切。我切@我切切切
    规则 = [^,。@|]+
    结果 = 我切 我切 我切 我切 我切切切 (gmatch)

    文本 = 讨   厌的  空格T _  T
    规则 = %s*
    结果 = 讨厌的空格T_T (gsub)

    文本 = a=3,    不作死=就不会死。  你要怎么=列表
    规则 = ……你居然想一步把这个分开,果然作死
    第一步:用%s*去掉所有空格
    第二步:将分隔符去掉利用"切切范例"
    第三步:将等号去掉并为table导入键值
    结果  = {[a]=3,["不作死"]="就不会死",["你要怎么"]="列表"}

    遇到不能一次分开的可以进行多次分割,若是动态文本则最好先转一个固定的格式。基本上处理字符串先是要格式比较好,后续处理才比较简单。至于-*+这三个的区别用处得多熟练,因为这三个很相似,所以很容易搞乱= =实在弄不清楚开SCITE去试试╮(╯▽╰)╭
    愉快的一天又过去了╮(╯▽╰)╭
    什么!居然写了一天!?o(>﹏<)o

    我的小结:

    match找到的内容,find找到的结果,sub子串

    函数名前有g表示全局,即对整个字符串处理,分割字符串可以用string.gsub。

  • 相关阅读:
    【从0安装】安装pycharm
    【从0安装】安装appium
    【从0安装】安装android sdk
    【从0安装】安装java jdk
    【从0安装】安装nodejs
    【技术解析】如何用Docker实现SequoiaDB集群的快速部署
    巨杉数据库助力民生银行、广发银行前台智慧化业务
    巨杉数据库入选Gartner数据库报告,中国首家入选厂商
    【操作教程】利用YCSB测试巨杉数据库性能
    巨杉数据库首批入选广州数字金融协会,引领大湾区数字金融创新
  • 原文地址:https://www.cnblogs.com/xdao/p/lua_pattern.html
Copyright © 2020-2023  润新知