lua字符串查找函数 string.find(s, pattern [, init [, plain]] )

本文深入解析Lua中string.find函数的使用,包括子串匹配和模式匹配,详细介绍了如何使用该函数进行字符串查找并获取匹配结果的位置。同时,文章还阐述了Lua中字符类的概念及其在模式匹配中的应用,如.*、%s等,并通过实例演示了如何利用这些字符类进行复杂匹配。

原文链接:http://blog.youkuaiyun.com/zhangxaochen/article/details/8084396


函数原型 string.find(s, pattern [, init [, plain]] )
 s: 源字符串
 pattern: 待搜索模式串
 init: 可选, 起始位置
 plain: 我没用过
 
 ① 子串匹配:
 

[plain]  view plain copy
  1. print(string.find("haha", 'ah') )  ----- 输出 2 3  


 注意: lua 里面数组或者字符串的字符, 其下标索引是从 1 开始, 不是 0
  string.find 默认情况下返回两个值, 即查找到的子串的 起止下标, 如果不存在匹配返回 nil。
 如果我们只想要 string.find 返回的第二个值, 可以使用 虚变量(即 下划线)
 

[plain]  view plain copy
  1. _, q=string.find("haha", 'ah')  
  2.  print(q)  ----- 输出 3  


 
 ② 模式匹配:
 

[plain]  view plain copy
  1. pair = " name = Anna "  
  2.  print(string.find(pair, "(%a+)%s*=%s*(%a+)") ---- 输出 2 12 name Anna  


 解释:
 如果 find 的第二个参数使用了某种匹配模式, 并且模式串里面带括号。 那么表示会“捕捉”括号括起来的模式匹配到的字符串。 捕捉, 当然会把他们作为返回值。这里捕捉了两下, 所以 find 多返回了两个值
 
 那么, 这个模式是怎么匹配的呢?
 Lua 支持的字符类有:
 
 .  任意字符
 %s 空白符
 %p 标点
 %c 控制字符
 %d 数字
 %x 十六进制数
 %z 代表0的字符
 %a 字母
 %l 小写字母
 %u 大写字母
 %w 字母数字
字符类的大写形式代表相应集合的补集, 比如 %A 表示除了字母以外的字符集
另外,* + - 三个,作为通配符分别表示:
*: 匹配前面指定的 0 或多个同类字符, 尽可能匹配更的符合条件的字串
+: 匹配前面指定的 1 或多个同类字符, 尽可能匹配更的符合条件的字串
-: 匹配前面指定的 0 或多个同类字符, 尽可能匹配更的符合条件的字串

于是, "(%a+)%s*=%s*(%a+)" 表示, 先匹配一个或多个字母, 然后是零个或多个空白符(比如空格), 然后是个 '=', 然后空白符, 然后字母。这样, 满足匹配的只有 "name = Anna"。 所以输出位置为 2 12.
因为捕获了两个 (%a+), 也就是 name, Anna 这两个单词, 所以还输出了这两个单词

另外, lua 使用 %1-%9 表示拷贝捕获。举例说:

[plain]  view plain copy
  1. s="abc \"it's a cat\""  
  2. _,_,_,q=string.find(s, "([\"'])(.-)%1")  
  3. print(q)  -----输出: it's a cat  


首先, [\"'] 表示匹配 双引号或者单引号, 因为有括号,所以引号被捕获。 然后匹配几个任意字符并且捕获他, 最后 %1 匹配与第一次捕获到的(即引号)相同的字串。所以整个模式匹配到的是 "it's a cat", 而第二次捕获的是去掉两头引号的字串, 即 it's a cat.

还有, '-' 与 '*' 到底有什么不同呢? 在上面, "([\"'])(.*)%1" 匹配到的结果与 '-' 是一样的。尽可能匹配更长, 尽可能匹配更短 究竟什么不同呢?看例子:

[plain]  view plain copy
  1. print( ("\"hello\" \"hello\""):find('"(.+)"') )  ----输出 1 15 hello" "hello  
  2. print( ("\"hello\" \"hello\""):find('"(.-)"') )  ----输出 1 7 hello  


* 尽可能长, 所以匹配了首尾两个 引号, 捕获了中间的 (hello" "hello)
- 尽可能短, 所以碰到第二个引号就说匹配完了, 因此只捕获了第一个 (hello)

原文链接:http://blog.youkuaiyun.com/zhangxaochen/article/details/8084396
 



### Lua 中文字符串匹配 在 Lua 中处理中文字符时,由于 UTF-8 编码的特点,直接使用 `string.find` 或者其他基于单字节字符的函数可能会遇到一些挑战。为了正确地进行中文字符串匹配,通常有两种主要的方法: #### 方法一:使用正则表达式中的 Unicode 类型 Lua 的标准库并不直接支持复杂的 Unicode 处理,因此对于简单的场景可以通过定义特定范围来匹配汉字。 ```lua local str = "你好, world!" local start_pos, end_pos = string.find(str, "[\194-\244][\128-\191]+") if start_pos then print("Found Chinese character at position:", start_pos) else print("No Chinese characters found.") end ``` 这种方法利用了 UTF-8 编码下多字节字符的第一字节和后续字节所处的不同区间来进行粗略判断[^1]。 #### 方法二:借助外部库增强功能 更推荐的方式是引入专门用于处理国际化文本的第三方库,比如 lpeg(Parsing Expression Grammars)。这些工具提供了更为强大灵活的功能去解析复杂结构的数据流,包括但不限于各种语言文字的支持。 ```lua -- 假设已经安装并加载lpeg模块 local lpeg = require 'lpeg' -- 定义一个模式用来识别任意数量连续的UTF-8编码形式下的汉字 local utf8_char = lpeg.P("\228\189\128") * lpeg.R("\128\191")^3 + ... -- 这里省略了一些可能的情况... local chinese_text_pattern = utf8_char^0 local input_string = "测试一下这个能否正常工作" for m in chinese_text_pattern:gmatch(input_string) do io.write(m .. "\n") end ``` 通过这种方式能够更加精确有效地完成对包含多种不同脚本系统的文档内容分析任务[^2]。 值得注意的是,在实际应用过程中还需要考虑更多细节问题,例如边界条件、异常情况等;同时也建议开发者关注官方文档以及社区资源获取最新最权威的信息指导开发实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值