搜索
aardio官方社区 门户 查看主题

模式匹配快速入门

发布者: Jacen.He | 发布时间: 2010-11-29 16:27| 查看数: 59935| 评论数: 71|帖子模式

提升学习效率的几个关键:

1、不要把什么都搞懂,先最简单最常用的搞懂,循序渐进
        例如新手,上来不要讲贪婪匹配,不要讲逻辑匹配,这个学习会让知识量增大,也完全没有必要。
别人学习进步快,并不是因为别人基础好,有好的教程,而是别人有聪明的学习方法,先拣够用的知识掌握好,在实际使用中象滚雪球那样积累,就怕你不动不敢滚出第一个雪球

2、要在实践中去掌握知识。
        知识是从来不能脱离实践的,例如贪婪匹配,逻辑匹配,你为什么不用学?你碰到了实际的需要,你会想:要是这里能.........多好啊? 你一查,还真有呢,你马上就懂了,几乎就是闪电的时间你就明白了,这就是实践中碰撞出来的知识火花。

3、要有信心
        任何你需要去学习的东西,哪怕他再简单,初次接触都会产生畏难的心理,把任何事做成功的一个必备条件就是有足够的勇气和信心,并不需要多少时间你就会发现:原来真的是会者不难






最新评论

Jacen.He 发表于 2010-11-29 16:27:23

[b][size=4]一个最简单的模式匹配代码: [/size][/b][quote]io.open() 结果 = string.match([colo

一个最简单的模式匹配代码:
io.open()

结果 = string.match("字符串","这里是模式串")
io.print( 结果 )

模式匹配 他里面有两个基本的东西。
1、模式 2、匹配

一、模式
用于表示字符或者某一类的字符。

1.1 字面值,一是说a表示a, b表示b,字面是什么就表示什么,这个不难理解。
io.open()
结果 = string.match("abcd","abc")
io.print( 结果 )

1.2 任意字符

另外还有两个非常特殊的预定义字符类,
一个小圆点"."表示任意字符,而一个冒号":"表示任意双字节字符(中文字)

1.3 预定义的字符类

\a 字母
\c 控制字符
\d 数字
\i 是否ASCII字符( 字节码 < 0x80 )
\l 小写字母
\p 标点字符
\s 空白符
\u 大写字母
\w 字母和数字
\x 十六进制数字
\n 换行符
\r 回车符
\f 换页符 '\x0c'
\v 匹配一个垂直制表符。等价于 '\x0b'
\z \0 字节码为0的字符,对于普通文本表示文本结束

没有任何必要去死记硬背上面的列表

大写表示反义,例如\D表示不是数字的字符。

io.open()
结果 = string.match("12345678","\d")
io.print( 结果 )
//显示 1

1.4 自定义的字符类,例如[abcd]表示字符是abcd其中一个,或者[a-z]表示a到z的所有字符都可以。

io.open()
结果 = string.match("12345678","[1230-9]")
io.print( 结果 )
//还是显示 1

1.5 自定义的字符,例如<a-zabcd> 他的语法与字符一样,但是他表示的是一,而不是其中一个
io.open()
结果 = string.match("12345678","<1230-9>")
io.print( 结果 )
// 显示 1234

二、修饰符
指定一个模式应当怎样去匹配。修饰符有很多种,而最常用的就是用来指定匹配次数。

p{2,3} 表示a出现2到3次
io.open()
结果 = string.match("12345678","\d{2,5}")
io.print( 结果 )
//显示 12345

p+  表示a出现1次到任意次数,等价于 p{1,}
io.open()
结果 = string.match("12345678","\d+")
io.print( 结果 )
//显示 12345678

p* 表示a出现0次到任意次数,等价于 p{0,}
io.open()
结果 = string.match("12345678","\d+\s*") //这里的"\s*"匹配零个或多个空格
io.print( 结果 ) //还是显示 12345678

Jacen.He 发表于 2010-11-29 16:27:30

模式匹配对正则表达式进行了简化,保留基本语法,牺牲一些功能换取效率。 例如模式串 [b][size=6]"[color=red]\d[/color][co

模式匹配对正则表达式进行了简化,保留基本语法,牺牲一些功能换取效率。

例如模式串 "\d+"  
前面红色的是模式表示匹配什么样的字符(\d表示数字),后面蓝色的是修饰符表示怎样去匹配、匹配多少个字符(+表示一个或任意多个),这就是模式匹配的全部内容了。很简单.

这里的"\d"还可以换成"[0-9]" ,他们的意思是一样的。
也可以换成 "[0123456789]",跟上面的意思也是一样的。

中括号表示自定义的一个字符集合,只要目标字符是其中的一个就匹配成功。
模式就这几种,很简单。

而后面的"+"表示匹配一次或多次,这个也可以写为"{1,}" 意思是一样的。

我们看一个身份证匹配的模式 "\d{15,18}"  这里指匹配15到18个数值

但是实际情况是:最后一位可能不是数值,可能是"x",也就是说可能是数值也可能是x,那么我们就要改为"\d{15,18}[\dx]"

那么再笨的人也能看出这个写错了,最后面去掉一位前面就不是15或18,而是14或17,
也就是正确的是
"\d{14,17}[\dx]"


但是别人还有可能把x大写啊,所以最终就是
"\d{14,17}[\dxX]"

所以说模式匹配很简单,但是他也不简单,其实上面的写法并不是绝对正确,但大多时候够我们用了。
再严格一点身份证他还不能是16位,17位。
所以你要这样写

io.open();
//打开控制台
结果 = string.match("身份证号码","\d{14,14}<\d\d\d>*[\dxX]"
)
io.print( 结果 )

象这些,你动手折腾很快会明白,别人灌输给你的知识永远没有自已探索到的理解深刻。

更进一步,19位,20位的数值都可能匹配成功,因为他只要匹配其中18位就成功了吗,这时候我们还要限定他前面后面都不能有其他的字符,这时就要指定边界。例如:

io.open();//打开控制台
结果 = string.match("身份证号码","^\d{14,14}<\d\d\d>*[\dxX]$" )
io.print( 结果 )

但是这样还有一个问题,如果身份证号码前后可能有空格怎么办呢?
\s表示所有空白字符,可能有也可能没有的修饰符就是"*"再改进:
io.open();//打开控制台
结果 = string.match("身份证号码","^\s*\d{14,14}<\d\d\d>*[\dxX]\s*$" )
io.print( 结果 )


如果身份证前后不仅仅是空格,还可能有别的字符,哪怎么办呢?

这里我们可以接触一个新的概念:边界
边界是在模式前面加一个表示否定的感叹号,例如
"!\d" 表示不是数字到数字交界的位置,这是一个试探性的匹配,匹配的是边界,匹配的字符串长度为0。
io.open();//打开控制台
sfz="dsf612323198608110000fgd"
结果 = string.match(sfz,
"!\d(\d{14}<\d\d\d>*[\dxX])![^\dxX]")
io.print( 结果 )

execute("pause")
io.close()


这些需要在实践中嗑碰出来的知识,如流水无形,无一定之规

点评

不考虑身份证号码前几位的特殊规律 如上的匹配方式不能排除掉17位数字,也不能排除掉14位数字+x  发表于 2010-11-29 23:49
Jacen.He 发表于 2010-11-29 16:27:37

可以熟练使用模式匹配中的括号,表示你精通了模式匹配。 [quote][b][size=5][ab][/size][/b] 中括号匹配指定字符中的[b][siz

可以熟练使用模式匹配中的括号,表示你精通了模式匹配。
[ab] 中括号匹配指定字符中的一个

<ab> 尖括号匹配一连串的字符。

p{2,3} 大括号指定模式重复匹配的次数

(p)
  而圆括号则设定模式匹配返回的结果,每增加一对圆括号,匹配函数就多一个返回值

《模式匹配语法参考》
http://bbs.aardio.com/doc/reference/libraries/kernel/string/pattern%20syntax.html

《模式匹配函数说明》
http://bbs.aardio.com/doc/reference/libraries/kernel/string/pattern%20matching.html

多结合实际案例练习,多到论坛跟大家交流。
然后你也尝试象我这样写教程,不要怕写的不好。
把自已的学习心得写出来。

建站 发表于 2010-11-29 23:12:32

太好了,这个一定得学,先收藏

太好了,这个一定得学,先收藏
vqimwr 发表于 2010-11-29 23:48:05

真不错,写得很明白。

真不错,写得很明白。
fantasynew 发表于 2010-11-30 00:04:44

[code]string.match("身份证号码","^\s*\d{14,14}<\d\d\d>*[\dxX]\s*$" ) [/code]不能排除14位数

  1. string.match("身份证号码","^\s*\d{14,14}<\d\d\d>*[\dxX]\s*$" )
复制代码
不能排除14位数字+x可以理解,需要加判断条件。
不能排除17位数字,看不明白为什么
落伍者 发表于 2010-11-30 10:01:29

[b]回复 [url=forum.php?mod=redirect&goto=findpost&pid=1236&ptid=172][color=Olive]f

回复 fantasynew 的帖子

^\s*\d{14,14}<\d\d\d>*[\dxX]\s*$
^起
\s空白
\s*0或者0以上的空白
\d数字
\d{14,14}连续14个数字
<\d\d\d>连续3个数字,放在<>内将他看作一个整体
<\d\d\d>*表示<>的3个数字可有可无,存在的时候必须是3的个一起出现
[\dxX]数字和x以及X内三个随便出现一个
$止
这个 表达式 除了能匹配出15,18位的 还能匹配出21,24 等
比赛的6楼  已经成功解决此问题
quickerfans 发表于 2010-11-30 14:57:52

这就是俺想看的教程。老大辛苦。一定要细细读,这个教程中提到的知识点,绝不能当问题再提出

这就是俺想看的教程。老大辛苦。一定要细细读,这个教程中提到的知识点,绝不能当问题再提出
cbtan 发表于 2010-11-30 15:57:05

继续加深匹配知识{:3_48:}

继续加深匹配知识
jihuxi 发表于 2010-11-30 15:57:17

[i=s] 本帖最后由 jihuxi 于 2010-11-30 16:00 编辑 [/i] 细细的看了一遍。 但是: io.open();//打开控制台

本帖最后由 jihuxi 于 2010-11-30 16:00 编辑

细细的看了一遍。
但是:
io.open();//打开控制台
sfz="dsf612323198608110000fgd"
结果 = string.match(sfz,"!\d(\d{14}<\d\d\d>*[\dxX])![\dxX]")
io.print( 结果 )
execute("pause")
io.close()
结果是null  

点评

晕,不是,这样改就少了一个数字了!!  发表于 2010-11-30 16:28
![\dxX] 改成 [!\dxX]  发表于 2010-11-30 16:27
jihuxi 发表于 2010-11-30 17:44:45

谢谢 cbtan{:3_59:}

谢谢 cbtan
cbtan 发表于 2010-11-30 17:49:11

[b]回复 [url=forum.php?mod=redirect&goto=findpost&pid=1320&ptid=172][color=Olive]j

回复 jihuxi 的帖子

,,我说的是错的!
jihuxi 发表于 2010-11-30 18:07:24

啊,我把 ![\dxX] 改成 [!\dxX] 运行结果为:612323198608110000

啊,我把 ![\dxX] 改成 [!\dxX]   运行结果为:612323198608110000
Auto 发表于 2010-12-24 00:41:18

看了一半,明天再看。

看了一半,明天再看。
freemanol 发表于 2010-12-24 10:25:46

收藏,收藏,再收藏

收藏,收藏,再收藏
wudijushi 发表于 2010-12-24 11:09:15

大力支持楼主的伟大贡献!

大力支持楼主的伟大贡献!
wpig 发表于 2010-12-25 14:44:59

看着怎么像是正则表达式了,是一个意思不?

看着怎么像是正则表达式了,是一个意思不?
wpig 发表于 2010-12-25 14:49:56

原来如此。明白了

原来如此。明白了
1234下一页

手机版|未经许可严禁引用或转载本站文章|站长邮箱|aardio.com|aardio官方社区 ( 皖ICP备09012014号 )

GMT+8, 2017-9-25 19:20 , Processed in 0.062500 second(s), 21 queries , WinCache On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表