本帖最后由 protectqiqi 于 2024-4-3 09:53 PM 编辑
Perl正则表达式之二 字符类和多字符匹配
这一节好难讲好难讲,但是一定要耐心看完,因为这节的内容如果不学会的话,是没法使用后面更高的功能的。我会尽量结合实际的例子把复杂的理论讲得简单一些。
先来看一个例子:在做纪晓芙或者韩世忠任务的时候会出现好几个npc,你需要对每个npc下一次kill命令,否则就只会打晕他们而不杀死。而每次npc的名字又都是不一样的,这样怎么匹配触发呢?这就要用到字符类和多字符匹配。
输入id here的话,我们能看到一个地方的所有人物的id。比如:
要保护七七哦 = protectqiqi 护院武师 = hu yuan 吴三桂 = wu sangui, wu, sangui 夏国相 = xia guoxiang, xia, guoxiang 巴朗星 = ba langxing, langxing, ba
玩家的id是一串连续的英文字母,而npc的姓和名中间有空格,而且可能会有个多个不同的id,每个id之间有逗号“,”隔开。利用这些规律,我们就可以做匹配啦。
Perl里有一些默认的字符类,如果你要匹配的字符在这个字符类里面,就会被匹配上。
字符类[a-z]就能用来匹配所有的小写英文字母。如果你在匹配语句里输入[a-z] [a-z] [a-z],那么任意三个连续的小写英文字母都会被匹配上,不管是什么小写字母,可以是abc,xyz,yes,not,等等等等。 abcdefg也能被匹配上,因为它的前三个字符也是连续的三个小写字母。 但是i77就会匹配不上,因为77不是小写字母。 Yes也会匹配不上,因为Y是大写字母。 a b c会匹配不上,因为三个字母中间有空格。 Hi, my name is 77.会被匹配上,因为这中间的name里面出现了三个连续的小写字母。
字符类\s则能用来表示空格。如果你在匹配语句里输入\s\s,那么任意两个连续的空格都会被匹配上。 10个连续的空格也会被匹配上,因为里面包含了两个连续的空格。
在字符类前面加个^(键盘上打shift+6)就能匹配不包含这个字符类的字符。比如: [^a-z]可以匹配不是小写字母的字符 [^0-9] 可以匹配不是数字的字符 [^a-zA-Z] 可以匹配不是英文字母(包括大小写)的字符 其他的字符类还有很多,我列在这个帖子的最下面了。
好了,那么[^a-zA-Z0-9_ ]可以用来匹配什么呢?这里面把字母、数字、下划线和空格都剔除了,那剩下来的不就是我们的中文了嘛。我一般就用这个字符类来匹配中文,虽然有些特殊字符和标点(比如【】,。)也会被匹配到。 那么[^a-zA-Z0-9_ ][^a-zA-Z0-9_ ][^a-zA-Z0-9_][^a-zA-Z0-9_ ]就能匹配上“护院镖师”和“要保护七七哦”。 [^a-zA-Z0-9_ ][^a-zA-Z0-9_ ][^a-zA-Z0-9_ ]既能匹配上“护院镖师”和“要保护七七哦”,又能匹配上“吴三桂”,“夏国相”或“巴朗星”。
到了这里,你会发现匹配的时候居然还要计算有多少个字符,根本不好用嘛。所以,多字符匹配就登场了。 在字符类的后面加上 ? * + {n,m} 等标记,就能匹配多个字符。
[字符类]? 能匹配只出现一次的字符。 [字符类]* 能匹配出现0到无数次的字符。 [字符类]+ 能匹配出现1次到无数次的字符。 [字符类]{n,m} 能匹配出现n次到m次的字符。 [字符类]{n,} 能匹配出现n次到无数次的字符。 [字符类]{,n} 能匹配出现0次到n次的字符。
好难理解哦,所以还是上实例吧。 [^a-zA-Z0-9_ ]+ 能匹配1到任意长度的中文,所以“吴三桂”,“夏国相”,“巴朗星”,“护院武师”,“要保护七七哦”都会被匹配上。 [^a-zA-Z0-9_ ]{4,} 能匹配长度4以上的中文,只有“护院武师”和“要保护七七哦”会被匹配上。 [a-z]{,2} 匹配两个以下连续的英文字母,所以只有hu,wu,ba。 \s+ 会匹配上中文名字和“=”之间所有的空格。
要保护七七哦 = protectqiqi 护院武师 = hu yuan 吴三桂 = wu sangui, wu, sangui 夏国相 = xia guoxiang, xia, guoxiang 巴朗星 = ba langxing, langxing, ba
好了,终极挑战来了。一个房间里那么多id,我只想匹配npc的id,不想匹配玩家的,不然我就会kill玩家,怎么办呢? 看规律!玩家和npc最大的区别就是id中间没有空格。所以就用: [^a-zA-Z0-9_ ]+\s+=\s[a-z]+\s[a-z]+.*
我们把这串拆开来看: [^a-zA-Z0-9_ ]+ 匹配前面的中文名字。 \s+ 匹配在=之前的那串空格。 = 就是匹配=。 \s 匹配=后面的那一个空格,因为是固定的只有一个空格,所以不需要用\s+。 [a-z]+ 匹配=后面,空格前面的那一串字母。一直到这里,玩家id都是会被匹配上的。 \s 匹配姓名之间的那个空格。最关键的区别就在这里了,玩家的id之间没有空格,只有npc有,所以这个\s就把玩家的id剔除出去了。 [a-z]+ 这是第二个[a-z]+,匹配npc的名字里的第二段英文,这里匹配到的内容就是以后我们要kill的。 .* 这里的.(一个小点)可以匹配任意字符。最后的这个字符类是拿来处理剩余的内容。像huyuan这样的npc在第二个[a-z]+之后就没有其他字符了。而别的npc后面还有, wu, sangui之类的字符。所以这里不用.+而用.*。
到了这里,你还不知道怎么对匹配到的id进行kill,这要等学会了提取变量后才能做到,等下次再讲。
看到这里你可能已经晕了,这一节确实很难很难,我用了好几天才完全搞明白的。如果你用一两天就研究明白了,就说明你的领悟能力和我的表达能力都很强!如果搞不明白就多花一点时间,这一节不搞清楚的话,后面是进行不下去的。
最后,我把其他的一些字符类都列在下面,以后用到的时候可以来查:
数字 [0-9] 小写字母 [a-z] 数字和大小写字母 [0-9a-zA-Z] \d 等同于 [0-9] \D 等同于 [^0-9] 即除了数字外的所有字符 \s 其实是 [\\t\r\n\f] 除了空格还能匹配tab和其他一些我不懂的字符。上面我说它只表示空格是为了不吓到你们。 \S 等同于[^\s] \w 等同于[0-9a-zA-Z_] 大小写字母,加上数字,再加上_(下划线) \W 等同于[^\w] 注意:拿它来匹配中文并不好,因为它会匹配到空格。 . (一个小点)可以匹配任意字符。
|