看懂《书源规则:从入门到入土》(4)正则入门



前言:在上一篇中 ,我们从网页里拿到了我们需要的文字。但是似乎有一点不是那么符合我们的预期。

那么,我们需要在字符串中找到有问题的子字符串,并替换成没有问题的字符串。

我们该怎样告诉程序我们要找的子字符串呢?



可能需要的工具:

1:正则表达式测试器 (比如说 查看链接 )

2:阅读/阅读pro 3.X版本



免责声明:

该系列(看懂《书源规则:从入门到入土》)图文仅供学习使用,自行编写的规则所造成的后果请自行承担,本人概不负责。

------------

🚨请注意,前方高能🚨



在上一章中,我们成功让阅读知道了这本书的作者是“作者:末世缘” 受虐滑稽

但很明显,这不是我们希望看到的结果。我们想要的是程序能知道这本书的作者叫“末世缘”而不是叫“作者:末世缘” t耐克嘴

那么,我们需要用到替换规则。替换规则的写法一般是

##正则表达式##替换内容

这种写法会把被正则表达式匹配到的内容替换成后面指定的内容,如果只是清除不需要替换成别的内容可以只写

##正则表达式



在上一章中,也许您已经通过规则

class.block_txt.0@tag.p.2@textNodes

获得了作者叫“作者:末世缘”了 受虐滑稽 。那么,现在的操作就很简单了,把“作者:”三个字删掉不就好了嘛。

class.block_txt.0@tag.p.2@textNodes##作者:

完事 受虐滑稽

这里,咱们就写出了本章第一个正则表达式,虽然这只是个简单模式的正则表达式只能匹配到“作者:”这三个字按顺序出现的情况,不过至少迈出了重要的第一步 无语

按照规范,正则表达式的写法应该是:

/匹配模式/搜索方式 (搜索方式为可选字段)

所以,上面的正确写法应该是“/作者:/”

那么,替换规则应该写成“##/作者:/”

完整的作者规则应该这样写

class.block_txt.0@tag.p.2@textNodes##/作者:/

----------

现在提个问题:如果需要匹配"fsxitutu"里的两个"u"该怎么办?

似乎/u/并没用

还记得上面说过后面还有个搜索方式的字段吗?这个字段留空的话之后匹配一次。

把你要使用的搜索方式标记加到搜索方式就可以启用对应的搜索方式了

再举个例子:如果要匹配fsxitutU里的两个u的话

/u/gi即可 无语

----------

在开始进阶篇前,我们先认识一个神奇的小杠杠“\”(反斜杠)。这个在正则表达式里叫转义字符,这个神奇的小杠杠可以把有特殊意义的符号变成普通字符,也能让某些字符具有特殊意义 受虐滑稽 。举个🌰:

n这是一个小写的英文字母“n”,但如果“\n”就表示一个换行符(LF , Line Feed)

$在正则表达式里表示结尾,但如果“\$”就表示一个普通的“$”(美元符号)

那么怎么表示一个普通的反斜杠呢?反斜杠是个特殊字符对不对?在特殊字符前面加反斜杠就会变普通字符对不对?那么写两个反斜杠("\\"),告诉电脑这是个普通的反斜杠就好了 受虐滑稽

特殊字符&转义字符(搬运自MDN):

位置符:

^(乘方号):表示字符串开头。

$(美元符号):表示字串结尾。

数量:

*(星号):匹配前一个字符0~N次。

+(加号):匹配前一个字符1~N次。

?(英文问号):匹配前一个字符0~1次。

{n}:指定数量。匹配前一个字符n次

{n,}:最小数量。匹配前一个字符至少n次(包含n)

{n,m}:数量范围。匹配前一个字符n~m次(包含n和m,如果某个值为0则忽略该值)

注:问号在其他表达式中有特殊意义,非单一意思!后面我会挨个解释。

表达式运算:

|(分隔号):匹配前面或后面的表达式。比如

/fs|tu/g会匹配到fsxitutu的"fs" "tu" "tu"

(x):捕获括号,记住括号里的内容供再次调用(通过

\+匹配组 的方式调用,如果是\n表示最后一个匹配组)。比如

/(tu)\1/和/tutu/的作用是一样的,都能匹配fsxitutu后面的“tutu”

(?:x):非捕获括号,就是把冒号后的字符串当成一个整体参与运算(视为一个字符)。比如

/(?:tu)+/就能匹配到fsxitutu里的“tutu”,但/tu+/只能匹配到第一个“tu”

x(?=y):先行断言。匹配x后面跟着y,但不能匹配到表达式x或y。比如

/xi(?=tu)/g只能匹配到fsxitutu的“xitu”不能匹配到“xi”和"tu”。

(?<=y)x:后行断言。匹配x前面是y,其它同理。

x(?!y):正向否定查找。匹配x后面不是y,其它同理。

(?<!y)x:反向否定查找。匹配x前面不是y,其它同理。

字符:

.(英文句号):默认匹配除换行符之外的任何单个字符。

[abc]:匹配里面的其中一个字符。特殊字符(比如“+”)可以不用转义。比如

/[abc]/g可以匹配abandon的"a" , "b" , "a"

[a-c]:匹配a~c其中一个字符(根据字符编码确定集合)。所以如果你写[A-z]会匹配到除大小写字母外还有"[" , "\" , "]" , "^" , "_" , "`" 受虐滑稽 ,如果你只想匹配大小写字母应该/[A-Z,a-z]/这样写

[^abc]:反向字符集。匹配不含里面任何一个字符的字符。比如在abcd中匹配/[^abc]/g则只有“d”被匹配。其他同理

[\b]:匹配退格符(0x0008)

转义字符:

\b:匹配字符边界。(概念:js中字符边界的定义是指[0-9,A-Z,a-z,_]这63个字符和非这63个字符之间的位置)

比如在“这1个”里面匹配/\b/g的话,“这”和“1”之间、“1”和“个”之间的小缝隙都会匹配

\B:匹配非字符边界。(敲黑板:在正则表达式中,如果\+字母有特殊意义的话,这个字母大小写的作用相反 受虐滑稽 )

\d:匹配一个数字。

\D:匹配一个非数字字符。

\s:匹配一个空白字符(比如说空格),等价于 [ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]

\S:匹配一个非空白字符。

\w:匹配一个单字字符,相当于[0-9,A-Z,a-z,_]

\W:匹配一个非单字字符。

(下面没有大小写的梗了 受虐滑稽 )

\cX:匹配一个控制符,X可以是任意大写英文名字。控制符列表详见 查看链接 (需要🛩️)

\xHH:匹配一个ASCII字符,H可以是[0-9,a-f]的字符(十六进制数字)。比如\x30表示匹配字符“0”

\uHHHH:匹配一个utf-16字符,要求同上

\f:匹配一个换页符(\u000c)

\n:匹配一个换行符(\u000a)

\r:匹配一个回车符(\u000d)

\t:匹配一个水平制表符(\u0009)

\v:匹配一个垂直制表符(\u000b)

\0:匹配NULL(\u0000)

----------

水了这么多,有什么用呢?

你们看小说的时候是不是很讨厌中间夹些www.xxxx.com

这样的网址。

那么我们在正文规则加个净化

##/(?:www)?(?:wap)?(?:m)?\.?\w+\.[a-z]{2,6}/g

世界瞬间就安静了 受虐滑稽

解析:

(?:www)?:可能有一个www,也可能没有(有0个 受虐滑稽 ),后面同理。

\.?:在上一条后面可能有一个点("."),也可能没有。

以上两条用来匹配无三级域或常见三级域,关于各级域名的划分自己去查,这不是本章科普的内容

\w+上一条后至少有一个字母或数字或下划线("_")。用来匹配二级域。

\.:上一条后有一个点。

[a-z]{2,6}:上一条后有2-5个小写字母连在一起。这个足够覆盖市面上大部分的顶级域了

-----------

结语&真心话&预告:

这章我承认,可能有点离题不怎么教写书源(话说我本来也没说教写书源吧 受虐滑稽 )。倒也不是说完全离题,写净化规则或写js处理字符串的时候还是要用到的。

正则表达式这东西入门容易精进难,自己去悟吧。评论区提问鄙人仅有限度回复(取决于我的精力 喝酒 )。

预告:

下一章也许是终章了,也有可能会分几小章,建议先去预习一下JavaScript。敬请期待下一章:js入门

-----------

引用:

正则表达式 - MDN: 查看链接