Lua正则表达式详解

发布时间:2023-05-23

一、基本语法

正则表达式是用来对字符串模式进行匹配和替换的工具。对于Lua而言,它包含了两个主要的函数:string.match和string.gsub。下面我们先看看基础语法。

  local str = "hello, lua regex"
  
  -- 匹配 "lua" 字符串
  local _, matchStr = string.match(str, "(%a+), (%a+)")
  print(matchStr) -- 输出 "lua"
  
  -- 替换 "lua" 为 "python"
  local replacedStr = string.gsub(str, "(%a+), (%a+)", "%1, python")
  print(replacedStr) -- 输出 "hello, lua, python"

如上所示,通过使用string.match或string.gsub函数进行匹配或替换。在匹配模式或替换模式中可以使用各种元字符以及转义字符。其中最常见的元字符包括:字符集合[ ],字符范围[ - ],重复匹配+、*、?和{}等,同时还有通过()来进行括号匹配并获取其中的字符串。

二、元字符详解

除了进行基本的匹配和替换,正则表达式还包含了许多元字符来辅助我们进行更加灵活的匹配或替换。下面我们来详细介绍几个常用的元字符。

1、字符集合 [ ]

字符集合是一个用来描述一组可以匹配的字符的元字符,例如[A-Z]表示匹配大写字母A到Z中的任意一个字符。除了使用单个字符,也可以使用范围表示法如:[0-9]表示匹配任意一个数字。

  local str = "hello, lua regex"
  
  -- 匹配所有小写字母
  local matchedStr = string.match(str, "([a-z]+)")
  print(matchedStr) -- 输出 "hello"

  -- 匹配除了小写字母之外的其它字符
  local replacedStr = string.gsub(str, "([^a-z]+)", "_")
  print(replacedStr) -- 输出 "_lua_regex"

2、特殊字符类

正则表达式还包含一些特殊字符类,如\d表示匹配任意一个数字字符,\s表示匹配任意一个空格字符,\w表示匹配任意一个字母或数字,\x表示匹配十六进制数。同时它们都有对应的大写形式

  local str = "hello, lua regex 3"
  
  -- 匹配数字字符
  local matchedStr = string.match(str, "(\%d+)")
  print(matchedStr) -- 输出 "3"

  -- 替换空格字符
  local replacedStr = string.gsub(str, "(\%s+)", "")
  print(replacedStr) -- 输出 "hello,luaregex3"

3、重复匹配+、*、?和{}

重复匹配是在正则表达式中对某个字符或某个字符集合进行重复匹配的元字符,其中最常用的是+、*和{}。

其中,+表示匹配前面的字符至少一次,*表示匹配前面的字符任意次数(包括0),?表示匹配前面的字符0次或1次,{n,m}表示匹配前面的字符至少n次,最多m次。

  local str = "abc ab abbb abbbb abcde"
  
  -- 匹配至少一个b的单词
  local matchedStr = string.match(str, "%w*ab+%w*")
  print(matchedStr) -- 输出 "ab", "abbb", "abbbb"

  -- 匹配至少4个b的单词
  local matchedStr = string.match(str, "%w*ab{4,}%w*")
  print(matchedStr) -- 输出 "abbbb"

三、转义字符

在许多情况下需要匹配一些特殊的字符(如.、+、*、?、(和)等)本身,这时候需要使用转义字符 \ 来进行转义匹配。

  local str = "3.14"
  
  -- 匹配小数点
  local matchedStr = string.match(str, "%.")
  print(matchedStr) -- 输出 "."

  -- 替换小数点
  local replacedStr = string.gsub(str, "%.", ",")
  print(replacedStr) -- 输出 "3,14"

四、使用场景

正则表达式可以在各种场景下使用,如从 HTML 代码中匹配标签及其属性、从日志中匹配出关键字、从邮件地址中取出用户名及域名等。下面我们来看一些实际应用场景。

1、从 HTML 代码中匹配标签及其属性

  local str = "<div id='myid' class='myclass'>Hello, Lua Regex</div>"
  
  -- 匹配div标签及其属性
  local matchedStr = string.match(str, "<div%s+([^>]+)>([^<]+)</div>")
  print(matchedStr) -- 输出 "id='myid' class='myclass'", "Hello, Lua Regex"

  -- 替换div标签为p标签
  local replacedStr = string.gsub(str, "(<div%s+)([^>]+)(>)", "<p%2≶")
  replacedStr = string.gsub(replacedStr, "(</div>)", "</p>")
  print(replacedStr) -- 输出 "<p id='myid' class='myclass'>Hello, Lua Regex</p>"

2、从日志中匹配出关键字

  local str = [[
    2022-01-01 08:01:01    ERROR    message: xxxxxx
    2022-01-01 08:02:02    DEBUG    message: xxxxxx
    2022-01-01 08:03:03    WARN     message: xxxxxx
    2022-01-01 08:04:04    ERROR    message: xxxxxx
  ]]
  
  -- 匹配所有错误信息
  for errorMsg in string.gmatch(str, "%d%d%d%d%-%d%d%-%d%d%s+%d%d:%d%d:%d%d%s+ERROR%s+message:%s+([^%c]+)") do
    print(errorMsg)
  end

3、从邮件地址中取出用户名及域名

  local str = "tom@example.com"
  
  -- 取出用户名及域名
  local matchedStr = string.match(str, "(%w+)@(%w+%.%w+)")
  print(matchedStr) -- 输出 "tom", "example.com"

五、总结

通过本文,我们详细介绍了Lua正则表达式的基础语法、元字符及其使用场景。正则表达式对于提取或处理字符串中特定的数据,具有十分重要的作用,希望本文能对大家有所启发。