精华内容
下载资源
问答
  • lua 正则匹配

    千次阅读 2016-12-05 16:52:26
    在OpenResty中,同时存在两套正则表达式规范: Lua 语言的规范和Nginx的规范,即使您对 Lua 语言中的规范非常熟悉,我们仍不建议使用 Lua 中的正则表达式。一是因为 Lua 中正则表达式的性能并不如 Nginx 中的正则...

    在OpenResty中,同时存在两套正则表达式规范: Lua 语言的规范和Nginx的规范,即使您对 Lua 语言中的规范非常熟悉,我们仍不建议使用 Lua 中的正则表达式。一是因为 Lua 中正则表达式的性能并不如 Nginx 中的正则表达式优秀;二是 Lua 中的正则表达式并不符合 POSIX 规范,而 Nginx 中实现的是标准的 POSIX 规范,后者明显更具备通用性。

    Lua 中的正则表达式与Nginx中的正则表达式相比,有5%-15%的性能损失,而且Lua将表达式编译成Pattern之后,并不会将Pattern缓存,而是每此使用都重新编译一遍,潜在地降低了性能。 Nginx 中的正则表达式可以通过参数缓存编译过后的Pattern,不会有类似的性能损失。

    o选项参数用于提高性能,指明该参数之后,被编译的Pattern将会在worker进程中缓存,并且被当前worker进程的每次请求所共享。Pattern缓存的上限值通过lua_regex_cache_max_entries来修改。

    --nginx.conf
    location /test {
        content_by_lua '
            local regex = [[\\d+]]
    
            -- 参数"o"是开启缓存必须的
            local m = ngx.re.match("hello, 1234", regex, "o")  
            if m then
                ngx.say(m[0])
            else
                ngx.say("not matched!")
            end
        ';
    }
    --在网址中输入"yourURL/test",即会在网页中显示1234。

    ngx.re.match

    语法:captures, err = ngx.re.match(subject, regex, options?, ctx?, res_table?)

    只有第一次匹配的结果被返回,如果没有匹配,则返回nil;或者匹配过程中出现错误时,也会返回nil,此时错误信息会被保存在err中。

    当匹配的字符串找到时,一个Lua table captures会被返回,captures[0]中保存的就是匹配到的字串,captures[1]保存的是用括号括起来的第一个子模式的结果,captures[2]保存的是第二个子模式的结果,依次类似。

        local m, err = ngx.re.match("hello, 1234", "[0-9]+")
        if m then
            -- m[0] == "1234"
        else
            if err then
                ngx.log(ngx.ERR, "error: ", err)
                return
            end
    
            ngx.say("match not found")
        end
    
    
    
    上面例子中,匹配的字符串是1234,因此m[0] == "1234",但是没有用括号括起来的子模式,因此,m[1],m[2]等均为nil。
    
    
    
        local m, err = ngx.re.match("hello, 1234", "([0-9])[0-9]+")
        -- m[0] == "1234"
        -- m[1] == "1"
    
    

    命名方式的捕获,从v0.7.14版本后开始支持,如下所示:

    例1:

        local m, err = ngx.re.match("hello, 1234", "([0-9])(?<remaining>[0-9]+)")
        -- m[0] == "1234"
        -- m[1] == "1"
        -- m[2] == "234"
        -- m["remaining"] == "234"
    
    

    例2:

        local m, err = ngx.re.match("hello, world", "(world)|(hello)|(?<named>howdy)")
        -- m[0] == "hello"
        -- m[1] == nil
        -- m[2] == "hello"
        -- m[3] == nil
        -- m["named"] == nil

    例2中,为什么m[1]等于nil?因为在给定的模式串中,最先匹配的是hello,因此,其他子模式在找到的匹配串中查找不到对应的匹配串,因此,除了hello子模式外,其他的子模式的匹配结果都是nil。一定要记住,是谁最先被匹配的。

    options选项可以是下面的取值的组合:

    a             锚定模式,只从头开始匹配. 
    
    d             DFA模式,或者称最长字符串匹配语义,需要PCRE 6.0+支持.
    
    D             允许重复的命名的子模式,该选项需要PCRE 8.12+支持,例如
    
                    local m = ngx.re.match("hello, world",
                                           "(?<named>\w+), (?<named>\w+)",
                                           "D")
                    -- m["named"] == {"hello", "world"}
    
    i             大小写不敏感模式.
    
    
    j             启用PCRE JIT编译, 需要PCRE 8.21+ 支持,并且必须在编译时加上选项--enable-jit,
    
                    为了达到最佳性能,该选项总是应该和'o'选项搭配使用.         
    
    
    J             启用PCRE Javascript的兼容模式,需要PCRE 8.12+ 支持. 
    
    
    m             多行模式.
    
    
    o             一次编译模式,启用worker-process级别的编译正则表达式的缓存.
    
    
    s             单行模式.
    
    
    u             UTF-8模式. 该选项需要在编译PCRE库时加上--enable-utf8 选项.
    
    U             与"u" 选项类似,但是该项选禁止PCRE对subject字符串UTF-8有效性的检查.
    
    x             扩展模式
    

    两个例子:

        local m, err = ngx.re.match("hello, world", "HEL LO", "ix")
        -- m[0] == "hello"
    
    
    
        local m, err = ngx.re.match("hello, 美好生活", "HELLO, (.{2})", "iu")
        -- m[0] == "hello, 美好"
        -- m[1] == "美好"
    
    

    第四个可选参数ctx可以传入一个Lua Table,传入的Lua Table可以是一个空表,也可以是包含pos字段的Lua Table。如果传入的是一个空的Lua Table,那么,ngx.re.match将会从subject字符串的起始位置开始匹配查找,查找到匹配串后,修改pos的值为匹配字符串的下一个位置的值,并将pos的值保存到ctx中,如果匹配失败,那么pos的值保持不变;如果传入的是一个非空的Lua Table,即指定了pos的初值,那么ngx.re.match将会从指定的pos的位置开始进行匹配,如果匹配成功了,修改pos的值为匹配字符串的下一个位置的值,并将pos的值保存到ctx中,如果匹配失败,那么pos的值保持不变。

        local ctx = {}
        local m, err = ngx.re.match("1234, hello", "[0-9]+", "", ctx)
             -- m[0] = "1234"
             -- ctx.pos == 5
    
    
    
        local ctx = { pos = 2 }
        local m, err = ngx.re.match("1234, hello", "[0-9]+", "", ctx)
             -- m[0] = "34"
             -- ctx.pos == 5
    
    

    注意:

    如果需要传入ctx参数,但并不需要第三个可选参数options时,第三个参数也不能简单去掉,这时需要传入一个空的字符串作为第三个参数的值。

    第四个可选参数还不是很熟悉,暂且留空。

    ngx.re.find

    语法:from, to, err = ngx.re.find(subject, regex, options?, ctx?, nth?)

    该方法与ngx.re.match方法基本类似,不同的地方在于ngx.re.find返回的是匹配的字串的起始位置索引和结束位置索引,如果没有匹配成功,那么将会返回两个nil,如果匹配出错,还会返回错误信息到err中。

    例子:

        local s = "hello, 1234"
        local from, to, err = ngx.re.find(s, "([0-9]+)", "jo")
        if from then
            ngx.say("from: ", from)
            ngx.say("to: ", to)
            ngx.say("matched: ", string.sub(s, from, to))
        else
            if err then
                ngx.say("error: ", err)
                return
            end
            ngx.say("not matched!")
        end
    
    
    
    输出结果:
    
    from: 8
    
    to: 11
    
    matched: 1234
    
    

    该方法相比ngx.re.match,不会创建新的Lua字符串,也不会创建新的Lua Table,因此,该方法比ngx.re.match更加高效,因此,在可以使用ngx.re.find的地方应该尽量使用。

    第五个参数可以指定返回第几个子模式串的起始位置和结束位置的索引值,默认值是0,此时将会返回匹配的整个字串;如果nth等于1,那么将返回第一个子模式串的始末位置的索引值;如果nth等于2,那么将返回第二个子模式串的始末位置的索引值,依次类推。如果nth指定的子模式没有匹配成功,那么将会返回两个nil。

        local str = "hello, 1234"
        local from, to = ngx.re.find(str, "([0-9])([0-9]+)", "jo", nil, 2)
        if from then
            ngx.say("matched 2nd submatch: ", string.sub(str, from, to))  -- yields "234"
        end
    
    

    ngx.re.gmatch

    语法:iterator, err = ngx.re.gmatch(subject, regex, options?)

    与ngx.re.match相似,区别在于该方法返回的是一个Lua的迭代器,这样就可以通过迭代器遍历所有匹配的结果。

    如果匹配失败,将会返回nil,如果匹配出现错误,那么还会返回错误信息到err中。

    
    
        local iterator, err = ngx.re.gmatch("hello, world!", "([a-z]+)", "i")
        if not iterator then
            ngx.log(ngx.ERR, "error: ", err)
            return
        end
    
        local m
        m, err = iterator()    -- m[0] == m[1] == "hello"
        if err then
            ngx.log(ngx.ERR, "error: ", err)
            return
        end
    
        m, err = iterator()    -- m[0] == m[1] == "world"
        if err then
            ngx.log(ngx.ERR, "error: ", err)
            return
        end
    
        m, err = iterator()    -- m == nil
        if err then
            ngx.log(ngx.ERR, "error: ", err)
            return
        end
    
    
    
    更多情时候,只需要把迭代过程放入一个while循环中即可:
    
        local it, err = ngx.re.gmatch("hello, world!", "([a-z]+)", "i")
        if not it then
            ngx.log(ngx.ERR, "error: ", err)
            return
        end
    
        while true do
            local m, err = it()
            if err then
                ngx.log(ngx.ERR, "error: ", err)
                return
            end
    
            if not m then
                -- no match found (any more)
                break
            end
    
            -- found a match
            ngx.say(m[0])
            ngx.say(m[1])
        end
    
    

    options选项的使用与ngx.re.match中的options选项的用法是一样的。

    注意点:

    ngx.re.gmatch返回的迭代器只能在一个请求所在的环境中使用,就是说,我们不能把返回的迭代器赋值给持久存在的命名空间(比如一个Lua Packet)中的某一个变量。

    ngx.re.sub

    语法:newstr, n, err = ngx.re.sub(subject, regex, replace, options?)

    该方法主要实现匹配字符串的替换,会用replace替换匹配的字串,replace可以是纯字符串,也可以是使用0,1等子模式串的形式,ngx.re.sub返回进行替换后的完整的字符串,同时返回替换的总个数;options选项,与ngx.re.match中的options选项是一样的。

        local newstr, n, err = ngx.re.sub("hello, 1234", "([0-9])[0-9]", "[$0][$1]")
        if newstr then
            -- newstr == "hello, [12][1]34"
            -- n == 1
        else
            ngx.log(ngx.ERR, "error: ", err)
            return
        end
    
    

    在上面例子中,01表示第一个子模式匹配的字串,以此类推。

    可以用大括号{}将相应的0,1,2…括起来,以区分一般的数字:

        local newstr, n, err = ngx.re.sub("hello, 1234", "[0-9]", "${0}00")
            -- newstr == "hello, 100234"
            -- n == 1

    如果想在replace字符串中显示进行转义(不要用反斜杠$对美元符号进行转义,这种方法不会得到期望的结果):

        local newstr, n, err = ngx.re.sub("hello, 1234", "[0-9]", "$$")
            -- newstr == "hello, $234"
            -- n == 1
    
    

    如果replace是一个函数,那么函数的参数是一个”match table”, 而这个”match table”与ngx.re.match中的返回值captures是一样的,replace这个函数根据”match table”产生用于替换的字符串。

        local func = function (m)
            return "[" .. m[0] .. "][" .. m[1] .. "]"
        end
        local newstr, n, err = ngx.re.sub("hello, 1234", "( [0-9] ) [0-9]", func, "x")
            -- newstr == "hello, [12][1]34"
            -- n == 1
    
    

    注意:

    通过函数形式返回的替换字符串中的美元符号$不再是特殊字符,而只是被看作一个普通字符。

    ngx.re.gsub

    语法:newstr, n, err = ngx.re.gsub(subject, regex, replace, options?)

    该方法与ngx.re.sub是类似的,但是该方法进行的是全局替换。

    看两个例子:

        local newstr, n, err = ngx.re.gsub("hello, world", "([a-z])[a-z]+", "[$0,$1]", "i")
        if newstr then
            -- newstr == "[hello,h], [world,w]"
            -- n == 2
        else
            ngx.log(ngx.ERR, "error: ", err)
            return
        end
    
    
    
        local func = function (m)
            return "[" .. m[0] .. "," .. m[1] .. "]"
        end
        local newstr, n, err = ngx.re.gsub("hello, world", "([a-z])[a-z]+", func, "i")
            -- newstr == "[hello,h], [world,w]"
            -- n == 2
    展开全文
  • Lua 正则匹配 gsub match

    千次阅读 2018-06-06 10:29:30
    lua 正则匹配式:(大写都是相反的). 任意字符 %a 字母 %c 控制字符%d 数字%l 小写字母%p 标点字符%s 空白符%u 大写字母%w 字母和数字%x 十六进制数字%z 代表0的字符--s:字符串,pattern:正则匹配字符规则...
    lua 正则匹配式:(大写都是相反的)
    .        任意字符 
    %a        字母 
    %c        控制字符
    %d        数字
    %l        小写字母
    %p        标点字符
    %s        空白符
    %u        大写字母
    %w        字母和数字
    %x        十六进制数字
    %z        代表0的字符
    --s:字符串,pattern:正则匹配字符规则,reps:要替换的字符串
    ():把括号中匹配的变量存到%1,%2,%3.....中,捕获括号内的字符
    string.gsub(s, pattern, reps)
    例子:
        s = "this is test,123456"
        print(string.gsub(s,"his","www"))=>twww is test,123456
        找到匹配的his,替换成www


        print(string.gsub(s,"(h)(is)",%2%1))=>tish is test,123456
        (匹配s中的"his"字符串,匹配的h放到%1变量中,匹配的is放到%2变量中,然后替换掉his为ish,%1表示符合模式的第一个匹配)
    string.gsub(s, pattern, func)
        gsub最后一个参数是函数,把pattern匹配的字符或者捕获的结果作为参数传递给func,然后把返回结果替换s中匹配字符
    string:match(reps)
        local filename="test.plist"
        print(filename:match(".+%.(%w+)$")) =>plist
        ($匹配结束符,.+匹配所有符号,%.匹配点号,(%w+)匹配最后一个点号后面的字符和数字,存到捕获的%1中,并且返回)


        print(filename:match(“.+()%.%w+$”)) =>5 
        (括号内是空,返回匹配字符括号后的一个字符的位置,即是返回匹配的最后一个点号的位置5)

    展开全文
  • local iter = string.match(str, "%-? [^%d+] ") local iter = string.match(str, "%-? (^%d+) ") ()无法试下^符号的作用只能用[]

    local iter = string.match(str, "%-? [^%d+] ")
    local iter = string.match(str, "%-? (^%d+) ")
    ()无法试下^符号的作用只能用[]

    展开全文
  • php/lua 正则匹配多行 单行注释

    千次阅读 2015-03-30 14:24:05
    $s = '/*aaaa sss */*/'; preg_match('@/\*.*?\*/@s', $s, $match); var_dump($match); 输出 array(1) { [0]=> string(13) "/*aaaa sss */" }php正则详细资粮参考地址
    <?php
    
    $s = '/*aaaa
    sss
    */*/';
    
    preg_match('@/\*.*?\*/@s', $s, $match);
    
    var_dump($match);

    输出

    array(1) {
      [0]=>
      string(13) "/*aaaa
    sss
    */"
    }
    php正则详细资粮参考地址

    匹配单行注释

    <?php
    $str = " 
    a = b; //asdf //saf
    b = c; //asdf
        ";
    $reg = '@\s*//.*$@m';
    
    $res = preg_replace($reg,'',$str);
    
    echo $res;

    输出

    a = b;
    b = c;


    再来一个lua版的

    local test = "int x; /* xx */ xx*/  int y; /* y */"
    
    function string.gfind(test, patten)
      local i,j = 0,0;
      return function()
        i,j = string.find(test, patten, j+1)
        if(i == nil) then -- end find
          return nil 
        end 
        return string.sub(test, i, j)
      end 
    end
    
    
    for v in string.gfind(test, "/%*.-%*/") do
      print(v)
    end
    输出

    /* xx */
    /* y */



    展开全文
  • Lua正则表达式匹配

    2021-03-14 19:15:45
    比如没有{n}匹配n次的规则,字符{和}都只是作为普通字符存在,字符|在posix标准正则表达式中表示或关系,在lua的pattern中也只是作为普通字符。 在lua中,一个正则表达式被称作为pattern,pattern中一对圆括号()包含的...
  • Lua 正则表达式 匹配

    千次阅读 2017-12-01 14:10:18
    . 任意字符 %s 空白符 %p 标点字符 %c 控制字符 %d 数字 %x 十六进制数字 %z 代表0的字符 ...+ 匹配前一字符1次或多次 ...* 匹配前一字符0次或多次;最长匹配 -- 先尽可能长地把本次匹配模式走完
  • 【lua】Lua正则表达式匹配邮箱

    千次阅读 2014-09-02 14:02:22
    function isRightEmail(str) if string.len(str or "") local b,e = string.find(str or "", '@') local bstr = "" local estr = "" if b then ...bstr = string.sub(str, 1, b-1) ...estr = string.sub(str, e+1,
  • 贴一段匹配中英文混合输入的代码 1 function dlg:onBtnOKClick() 2 local input = self:getInputNewContent() 3 if input == "" then 4 flytip( " 输入不能为空 " ) 5 return 6 end...
  • lua正则表达式

    2019-12-21 16:51:44
    Lua中使用正则表达式进行模式匹配的string库函数有这四个: string.find(str, pattern[, init[, plain]]) string.gsub(str, pattern, repl[, n]) string.match(str, pattern[, init]) string.gmatch(str, ...
  • lua 正则表达式使用

    2016-01-23 14:51:28
    lua 正则表达式使用在使用lua的string库匹配模式的时候,对于一些比较麻烦的处理,搜网页总是不得其所,下面是接触到的一些经典用法 string.find string.gsub string.sub * 对这三个方法的基本使用不概述了* 现有一...
  • Lua 正则表达式

    2020-03-12 14:26:41
    --[[学习模式匹配]] --匹配规则A: --.(点) 与任何字符配对 --%a 与任何字母配对 [alphabet] --%d 与任何数字配对 [digit] --%w 与任何字母/数字配对 [word] --匹配规则B: --%s 与任何空白配对 --%l 与任何...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 206
精华内容 82
关键字:

lua正则匹配