如何学习正则表达式

文章目录

0.前言

按照我的学习顺序,整理此文章

首先推荐一个在线的工具(个人感觉很好用):https://regex101.com/

1.正则表达式的概念

1.1什么是正则表达式

正则表达式是一组由字母和符号组成的特殊文本,可以用它来从文本中找出满足你想要的格式的句子。

1.2正则表达式的用途

计算机诞生初期处理的信息几乎都是数值,但是时过境迁,今天我们使用计算机处理的信息更多的时候不是数值而是字符串,正则表达式就是在进行字符串匹配和处理的时候最为强大的工具,绝大多数语言都提供了对正则表达式的支持。
常见的场景如下:

  1. 验证数据的有效性
  2. 替换文本内容
  3. 从字符串中提取子字符串
  4. 网页抓取目标数据

2.正则表达式语法规则

github上一篇高星文章

2.1元字符

元字符描述
.句号匹配任意单个字符除了换行符。
[ ]字符种类。匹配方括号内的任意字符。
[^ ]否定的字符种类。匹配除了方括号里的任意字符
*匹配>=0个重复的在*号之前的字符。
+匹配>=1个重复的+号前的字符。
?标记?之前的字符为可选.
{n,m}匹配num个大括号之前的字符或字符集 (n <= num <= m).
(xyz)字符集,匹配与 xyz 完全相等的字符串.
|或运算符,匹配符号前或后的字符.
\转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \
^从开始行开始匹配.
$从末端开始匹配.

2.2简写字符集

简写描述
.除换行符外的所有字符
\w匹配所有字母数字,等同于 [a-zA-Z0-9_]
\W匹配所有非字母数字,即符号,等同于: [^\w]
\d匹配数字: [0-9]
\D匹配非数字: [^\d]
\s匹配所有空格字符,等同于: [\t\n\f\r\p{Z}]
\S匹配所有非空格字符: [^\s]
\f匹配一个换页符
\n匹配一个换行符
\r匹配一个回车符
\t匹配一个制表符
\v匹配一个垂直制表符
\p匹配 CR/LF(等同于 \r\n),用来匹配 DOS 行终止符

2.3理解零宽断言

也就是非捕获先分两类:
一类:回顾,一类预测,然后再分判断,一个是等于,另一个是不等于
零宽断言分为四种

符号分类描述使用示例
?=预判&等于正向零宽断言-存在表达式必须跟随着断言中定义的表达式a(?=b)
?!预判&不等于正向否定零宽断言-排除必须不跟随着断言中定义的表达式a(?!=b)
?<=回顾&等于反向零宽断言-存在必须跟随着断言中定义的表达式(?<b)a
?<!回顾&不等于反向否定零宽断言-排除必须不跟随着断言中定义的表达式(?!<b)a

当人还有别的叫法,意思一样理解就行~

2.3.1正向零宽断言与反向零宽断言的区别

  1. 正向零宽断言——(?=)
    用于筛选所有匹配结果,筛选条件为表达式之后必须跟着断言中定义的表达式
    即:找a后面跟着b的条件,则ae是匹配不上的
    在这里插入图片描述
    零宽就是宽度为零的字符则正向零宽断言如果不写其他条件的情况下,看他所在的位置为b的前面
    在这里插入图片描述

  2. 反向零宽断言——(?<=)
    用于筛选所有匹配结果,筛选条件为其前跟随着断言中定义的表达式。
    在这里插入图片描述
    反向零宽断言如果不写其他条件的情况下,看他所在的位置为b的后面
    在这里插入图片描述

2.3.2正向否定零宽断言与反向否定零宽断言

  1. 正向否定零宽断言——(?!)
    筛选条件为其后不跟随着断言中定义的表达式,所以选中ae中的a
    在这里插入图片描述
    正向否定零宽断言如果不写其他条件的情况下,看他所在的位置为没有b的前面,有b的前面都没有竖线
    在这里插入图片描述

  2. 反向否定零宽断言——(?<!)
    筛选条件为其前不跟随着断言中定义的格式
    在这里插入图片描述
    反向否定零宽断言如果不写其他条件的情况下,看他所在的位置为没有b的后面,有b的前面都没有竖线
    在这里插入图片描述

2.4标志

标志也叫模式修正符,因为它可以用来修改表达式的搜索结果。 这些标志可以任意的组合使用,它也是整个正则表达式的一部分。

标志描述
i忽略大小写。
g全局搜索。
m多行修饰符:锚点元字符 ^ $ 工作范围在每行的起始。

2.5贪婪匹配与惰性匹配 (Greedy vs lazy matching)

正则表达式默认采用贪婪匹配模式,在该模式下意味着会匹配尽可能长的子串。我们可以使用 ? 将贪婪匹配模式转化为惰性匹配模式。

贪婪匹配模式

"/(.*at)/" => The fat cat sat on the mat. 

惰性匹配模式

"/(.*?at)/" => The fat cat sat on the mat. 

3.接着就是练习啦

看这篇文章~

3.1. 分组提取/非捕获组

分组,是正则里一个非常重要的概念,我们需要针对某个区域提取数据,往往需要依赖分组。而分组,其实就是正则里()括住的部分。

3.1.1分组提取

需求:在分组1中匹配meta中author属性的值
源串:
<meta author="Zjmainstay" />
another author="Zjmainstay too"
预期:分组1得到Zjmainstay
正则:/<meta author="(.*?)"/
题样:https://hiregex.com/r/B7aH84/1

3.1.2非捕获组

针对上面的分组,有时候,我们并不需要捕获某个分组的内容,我们可以使用非捕获组(?:表达式),从而不捕获表达式部分内容到分组中。

需求:匹配每行字母个数是偶数个的数据,每行数据不为空,正则不能存在分组1
源串:
a
ab
abc
abcd
预期:
匹配得到 ab 和 abcd,不包含分组1
正则:/^(?:[a-z][a-z])+$/m
题样:https://hiregex.com/r/hcspP2/1

3.2. 单字符或

或条件是正则使用过程中常用的概念,比如,密码由字母或数字组成,这里就用到了或条件,而且,由于字母或数字都是单个字符,因此,可以使用[a-z0-9]这样的单字符或语法实现。
常犯错误:匹配a或b写成[a|b],此表达式实际上表示a或b或|,在[]内部的|表示其本身,注意区分(a|b)表示a或b的写法。

(2)单字符或

需求:匹配由 A/S/D/F 4个字母(区分大小写)组成的长度为3字符串
源串:
ABC
ASD
ADS
ASF
BBC
A|S
A|D
ASDF
预期:以[]元字符获得3个字母的或集,匹配 ASD/ADS/ASF 3组数据
正则:/^[ASDF]{3}$/m
题样:https://hiregex.com/r/JHkPH1/1

3.3. 多字符或

相对单字符或条件,多字符或也是很常见的,比如,我们需要匹配http或ftp两个协议头的url,就需要^(http|ftp)://.+$这样的语法来实现。

需求:匹配每行数据中以.jpg/.jpeg/.png/.gif结尾的图片名称(含后缀)
源串:
image.jpg
image.jpeg
image.png
image.gif
not_image.txt
not_image.doc
not_image.xls
not_image.ppt
预期:匹配 image.jpg/image.jpeg/image.png/image.gif 4个结果
正则:/^.+\.(?:jpg|jpeg|png|gif)$/m
题样:https://hiregex.com/r/hyoAJ1/1

3.4. 分组引用

前面介绍了分组,那某个分组在我们匹配过程中重复出现,又该如何处理?分组引用恰恰解决这个问题。比如,匹配出现重复单词的一行数据,我们可以这么写(多行模式):/^.?(\b\S+\b).?\1.*$/m,\1表示引用前面分组1中匹配到的内容,也就是重复的单词内容。

需求:匹配连续相同3次的数字
源串:
111
121
112
222
预期:匹配 111/222 两组数据
正则:/(\d)\1\1/
题样:https://hiregex.com/r/2p93c/1

3.5. 匹配换行数据

“我的正则本来好好的,突然不行了!”这个是很多正则新人遇到的问题,而这个问题,很多时候,就是因为原来正则中的.不能匹配新数据里的换行导致的。这时候,只需要把.改成[\s\S]这样的表达式就可以了。这个表达式表示空格或非空格,也就是任意字符啦。

需求:分别使用单行模式和普通模式匹配id="author"的div中数据,div标签不在同一行
源串:
<div id="author">
Zjmainstay
</div>
预期:Zjmainstay
正则1/<div id="author">(.*?)<\/div>/s
正则2/<div id="author">([\s\S]*?)<\/div>/
题样:https://hiregex.com/r/tYcOO3/1

3.6. 存在(或)

3.6.1匹配多种或条件的数据,没有特殊限制

需求:匹配每行中包含“作者”或者“读者”的数据
源串:
本文的作者是Zjmainstay
本文有很多读者
读者可以是任何一个地方的人
这里的任何一个地方说明读者也能在国外
什么乱七八糟的推理
你不匹配我,凭什么要我推荐你的博客 www.zjmainstay.cn
预期:匹配
本文的作者是Zjmainstay
本文有很多读者
读者可以是任何一个地方的人
这里的任何一个地方说明读者也能在国外
正则:/.*(?:作者|读者).*/
题样:https://hiregex.com/r/n2FGC1/1

3.6.2匹配多种或条件的数据,有特殊限制(不使用环视)

需求:匹配每行中“读者”在开头或结尾的数据
源串:
本文作者是Zjmainstay,有很多读者
读者可以是任何一个地方的人
这里的任何一个地方说明读者也能在国外
预期:匹配
本文作者是Zjmainstay,有很多读者
读者可以是任何一个地方的人
正则:/^读者.+$|^.+读者$/m
题样:https://hiregex.com/r/L5kYV/1

3.6.3匹配多种或条件的数据,有特殊限制(使用环视)

需求:匹配每行中“读者”在开头或结尾的数据
源串:
本文作者是Zjmainstay,有很多读者
读者可以是任何一个地方的人
这里的任何一个地方说明读者也能在国外
预期:匹配
本文作者是Zjmainstay,有很多读者
读者可以是任何一个地方的人
正则:/^(?=读者|.*读者$).+$/m
题样:https://hiregex.com/r/9FJHT4/1

3.7. 存在(与)

3.7.1校验密码必须包含字母、数字和特殊字符,6-16位

需求:校验密码必须包含字母、数字和特殊字符,6-16位,假定特殊字符为 -_= 三个字符
源串:
12345
123456
1234561234561234
12345612345612345
a1234
a12345
-1234
-12345
a-123
a-1234
a-1234a-1234a-12
a-1234a-1234a-1234
aaaaa
aaaaaa
-_=-_
-_=-_=
预期:匹配
a-1234
a-1234a-1234a-12
正则:/^(?=.*?[a-z])(?=.*?[0-9])(?=.*?[_\-=])[a-z0-9_\-=]{6,16}$/m
题样:https://hiregex.com/r/6kEWf4/1

3.8. 特殊限制(环视否定)

3.8.1使用\d{1,3}匹配1-999的数据,不能以0开头

需求:使用\d{1,3}匹配每行中1-999的数据,不能以0开头
源串:
1
10
100
999
1000
01
001
预期:匹配
1
10
100
999
正则:/^(?!0)\d{1,3}$/m
题样:https://hiregex.com/r/QIP8F4/1

3.8.2匹配除了span标签外的所有标签

需求:匹配除了<span>内容</span>标签外的所有<tagName>内容</tagName>格式标签
源串:
<div>匹配我</div>
<span>不匹配我</span>
<p>匹配我</p>
<i>匹配我</i>
预期:匹配
<div>匹配我</div>
<p>匹配我</p>
<i>匹配我</i>
正则:/<((?!span>)[^>]+)>.*?<\/\1>/
题样:https://hiregex.com/r/Y77Z51/1

3.9. 替换分组使用

3.9.1给源串每个链接加上http://www.zjmainstay.cn前缀

需求:给源串每个链接加上http://www.zjmainstay.cn前缀
源串:
<a id="link-1" href="/regexp-one">正则文章合集(All In One)</a>
<a id="link-2" href="/my-regexp">正则入门教程</a>
<a id="link-3" href="/deep-regexp">正则高级教程</a>
<a id="link-4" href="/regexp-lookaround">正则环视详解</a>
<a id="link-5" href="/php-curl">PHP cURL应用</a>
预期:替换得到
<a id="link-1" href="http://www.zjmainstay.cn/regexp-one">正则文章合集(All In One)</a>
<a id="link-2" href="http://www.zjmainstay.cn/my-regexp">正则入门教程</a>
<a id="link-3" href="http://www.zjmainstay.cn/deep-regexp">正则高级教程</a>
<a id="link-4" href="http://www.zjmainstay.cn/regexp-lookaround">正则环视详解</a>
<a id="link-5" href="http://www.zjmainstay.cn/php-curl">PHP cURL应用</a>
查找:/<a id="link-\d+" href="/
替换:$0http://www.zjmainstay.cn
题样:https://hiregex.com/r/gTDjO3/1

3.9.2将每行数据格式化为一条SQL语句

需求:将每行特定格式数据格式化为SQL语句
源串:
1 2017-04-11 Zjmainstay
2 2017-04-12 Nobody
3 2017-04-13 Somebody
预期:替换得到
INSERT INTO table_log(`id`, `created_at`, `author`) values('1', '2017-04-11', 'Zjmainstay');
INSERT INTO table_log(`id`, `created_at`, `author`) values('2', '2017-04-12', 'Nobody');
INSERT INTO table_log(`id`, `created_at`, `author`) values('3', '2017-04-13', 'Somebody');
查找:/(\d+) ([\d-]+) (\S+)/
替换:INSERT INTO table_log(`id`, `created_at`, `author`) values('$1', '$2', '$3');
题样:https://hiregex.com/r/RIQTP4/1

3.10. 分组可选

3.10.1分组可选

需求:判断如果单词以A开头,匹配Apple;如果单词以B开头,匹配Banana;否则匹配Empty
源串:
Angle
Apple
Banana
Best
Empty
预期:匹配
Apple
Banana
Empty
正则:/^((A)?|(B)?)?(?(1)(?(2)pple|(?(3)anana|(?!)))|Empty)/m
题样:https://hiregex.com/r/nkwBu1/1

3.10.2分组可选与分组引用

需求:匹配html标签的属性值,属性值可以由双引号、单引号、无单双引号定界
源串:
<div id="I'm Zjmainstay" class="name" data-year=2017 age='27'>
预期:分组匹配
I'm Zjmainstay
author
2017
27
正则:/(\S+)\s*=\s*(['"])?((?(2)(?:(?!\2).)+|[^\s>]+))\2?/
题样:https://hiregex.com/r/4dIVO3/1

3.11. 单字符拆分(数字)

匹配0.00-100.00的数值,可以有0-2位小数

需求:匹配0.00-100.00的数值,可以有0-2位小数,不能以小数点结尾,不能以2个以上的0开头
思路:(100|10-99|0-9) + 0-2小数位 + 排除小数点结尾、2个以上0开头的情况
源串:
0
1
0.0
0.00
9.00
18.00
27.0
36.00
45.00
54.00
63.00
72.00
81.00
90.00
99.99
100.00
0.
001
100.01
100.001
101
预期:匹配0.00~100.00
正则:/^(?!0\d)(?:100(?:\.0{1,2})?|[1-9]?\d(?:\.\d{1,2})?)$/
题样:https://hiregex.com/r/mCpsV4/1

3.12. 贪婪模式

贪婪模式,正则会优先尽可能多地匹配能匹配到的内容。当剩余正则匹配剩余部分字符(源串)但无法满足匹配时,贪婪部分回溯,吐出已匹配的内容,尝试满足剩余部分字符的匹配。

3.12.1匹配链接中的文件名

需求:利用贪婪模式,分组1得到每行链接中的文件名
源串:
http://localhost.com/a/b/c/d/file1.txt
https://localhost.com/a/b/file2long.jpg
预期:分组0匹配行数据,分组1匹配文件名
file1.txt
file2long.jpg
正则:/.*\/(.*)/m
题样:https://hiregex.com/r/wvCml3/1

3.12.2限定字符贪婪优化匹配性能

需求:匹配div id="author"的标签内容
源串:
<div id="author" class="author-text something-useless">Zjmainstay</div>
预期:利用贪婪模式去掉div中的噪点(无关数据),分组1匹配到Zjmainstay
正则:/<div id="author"[^>]*>(.*?)<\/div>/
题样:https://hiregex.com/r/U6cJb4/1

3.13. 非贪婪模式

贪婪模式,正则会优先尽可能少地匹配能匹配到的内容。当剩余正则匹配剩余部分字符(源串)但无法满足匹配时,非贪婪部分继续匹配更多内容,尝试满足剩余部分字符的匹配。

匹配p标签内容
需求:匹配p标签内容
源串:
<p>内容1</p><p>内容2</p>
预期:
在分组1中匹配到内容1和内容2
正则:/<p>(.*?)<\/p>/m
题样:https://hiregex.com/r/dfiUF4/1

3.14. 占用模式(PCRE)

贪婪模式后再加一个+量词,如.++,效果是贪婪而且不回溯。
暂时没有想到应用场景。

3.15. |字符分界(|的作用域)

|作为或条件分隔符,它的分隔区间常常存在误用。在使用|字符的过程中,我们常常需要结合()来对它进行限定。如,([0-9]+|[a-z]+)$表示纯数字或纯字母,如果没有(),那它又是另一种意思了。^[0-9]+|[a-z]+$等价于[0-9]+或[a-z]+$,因此,它表示数字开头或者字母结尾,跟我们的需求有了很大的差别。

需求:在分组1中匹配css或script的链接
源串:
<script src="main.min.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="main.css">
预期:
main.min.js
main.css
正则:/<(?:script|link)[^>]*?(?:href|src)="([^"]+)"/
题样:https://hiregex.com/r/UAc4O2/1

3.16. 元字符转义

元字符,指正则中有特殊意义的字符,如.表示匹配除了换行符以外的任意字符,这个.就是元字符。在正则书写过程中,如果我们真的要匹配这个.,就需要对它进行转义,而不是让它使用正则的含义,比如,匹配域名里的.,我们就要写成/zjmainstay.cn/这样的正则。

需求:表达式格式固定,提取其中的数值
源串:
(20+170)-5*1/5=?
预期:
A:20
B:170
C:5
D:1
E:5
F:?
正则:/\((\d+)\+(\d+)\)-(\d+)\*(\d+)\/(\d+)=(\?)/
替换:A:$1\nB:$2\nC:$3\nD:$4\nE:$5\nF:$6
题样:https://hiregex.com/r/DhPaI1/1

3.17. 分隔符绕过(PCRE)

有时候,如果该语言支持多种分隔符,在写正则的过程中通常会通过规避分隔符的方式,减少对分隔符的转义,让正则看起来更清晰,写起来更舒服,当然,js中是不支持的。

需求:在不对/转义的情况下匹配p标签内容
源串:
<p>内容1</p><p>内容2</p>
预期:
在分组1中匹配到内容1和内容2
正则:@<p>(.*?)</p>@m
题样:https://hiregex.com/r/hwDnS1/1

3.18. 匹配溢出排除

匹配溢出,这不是一个术语名词,是我自己的叫法,主要指正则匹配内容超出了我们预期,导致匹配得到非预期的结果。

3.18.1div标签匹配溢出

需求:匹配内容为数字的div
源串:
<div class="aaa bbb">ABC</div><div class="bbb ccc">123</div>
预期:
<div>123</div>
错误正则:/<div.*?>\d+<\/div>/
正则:/<div[^>]*>\d+<\/div>/
题样:https://hiregex.com/r/CNNqb1/1

3.18.2多字符排除

需求:匹配不包含某个单词或词语的内容
源串:
http://www.zjmainstay.cn
http://www.baidu.com
http://www.qq.com
预期:
http://www.zjmainstay.cn
http://www.qq.com
正则:/^http:\/\/(?:(?!baidu).)+$/m
题样:https://hiregex.com/r/KyeQf1/1

3.18.3多字符排除

需求:匹配不包含某个单词或词语的内容
源串:
A("Excalibur", "誓约胜利之剑", LONG_SWORD, (SPFX_NOGEN | SPFX_RESTR | SPFX_SEEK | SPFX_DEFN | SPFX_INTEL | SPFX_SEARCH), 
  0, 0, PHYS(5, 10), DRLI(0, 0), NO_CARY, 0, A_LAWFUL, PM_KNIGHT, NON_PM, 4000L, NO_COLOR);
/*
 * Stormbringer only has a 2 because it can drain a level,
 * providing 8 more.
 */
A("Stormbringer", "兴风者", RUNESWORD,
  (SPFX_RESTR | SPFX_ATTK | SPFX_DEFN | SPFX_INTEL | SPFX_DRLI), 0, 0,
  DRLI(5, 2), DRLI(0, 0), NO_CARY, 0, A_CHAOTIC, NON_PM, NON_PM, 8000L,
  NO_COLOR);
/*
 * Mjollnir will return to the hand of the wielder when thrown
 * if the wielder is a Valkyrie wearing Gauntlets of Power.
 */
A("Mjollnir", "雷神之锤", WAR_HAMMER, /* Mjo:llnir */
  (SPFX_RESTR | SPFX_ATTK), 0, 0, ELEC(5, 24), NO_DFNS, NO_CARY, 0,
  A_NEUTRAL, PM_VALKYRIE, NON_PM, 4000L, NO_COLOR);
A("Cleaver", "撕裂者", BATTLE_AXE, SPFX_RESTR, 0, 0, PHYS(3, 6), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_BARBARIAN, NON_PM, 1500L, NO_COLOR);
/*
 * Grimtooth glows in warning when elves are present, but its
 * damage bonus applies to all targets rather than just elves
 * (handled as special case in spec_dbon()).
 */
A("Grimtooth", "邪兽之牙", ORCISH_DAGGER, (SPFX_RESTR | SPFX_WARN | SPFX_DFLAG2),
  0, M2_ELF, PHYS(2, 6), NO_DFNS,
  NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ORC, 300L, CLR_RED);
/*
 * Orcrist and Sting have same alignment as elves.
 *
 * The combination of SPFX_WARN+SPFX_DFLAG2+M2_value will trigger
 * EWarn_of_mon for all monsters that have the M2_value flag.
 * Sting and Orcrist will warn of M2_ORC monsters.
 */
A("Orcrist", "杀兽剑", ELVEN_BROADSWORD, (SPFX_WARN | SPFX_DFLAG2), 0, M2_ORC, PHYS(5, 0), 
  NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 2000L, CLR_BRIGHT_BLUE); /* bright blue is actually light blue */
预期:
Excalibur=誓约胜利之剑
Stormbringer=兴风者
Mjollnir=雷神之锤
Cleaver=撕裂者
Grimtooth=邪兽之牙
Orcrist=杀兽剑
查找:/A\("([^"]+)", "([^"]+)[\s\S]*?(?=A\("([^"]+)", "([^"]+)|$)/
替换:$1=$2\n
题样:https://hiregex.com/r/D4gQB1/1

3.19. 环视循环提取格式化

在数据处理过程中,经常遇到一些格式化处理,比如简单地将一批数据格式化为SQL(参考9.2),还有复杂的需要对一行数据的某部分进行循环提取,然后格式化为特定格式。


需求:循环提取每行数据的分支部分和固定部分,格式化为特定格式
源串:
BBB|CCC|DDD=AAA
FFF|GGG|HHH|III|JJJ|KKK=EEE
预期:
BBB=AAA
CCC=AAA
DDD=AAA
FFF=EEE
GGG=EEE
HHH=EEE
III=EEE
JJJ=EEE
KKK=EEE
查找:/([^|=\r\n]+)[|]?(?=.*?=([^\n]+))(?:=[^\n]+)?[\n]?/
替换:$1=$2\n
题样:https://hiregex.com/r/ntZT84/1

3.20. 环视+递归引用表达式

PCRE支持使用(?R)引用整个正则表达式,使用(?1)引用分组1的正则表达式,在处理的数据的过程可以通过这种方式让表达式无限扩展,类似平衡组的方式,平衡匹配目标数据。

需求:取出该条字符串中所有的()括起来的部分,包括括号
源串:
(if((left(A5,2)=39)&(A5<>3905)&(A5<>3908)&(A5<>3909),(V5>0)&(T5=0)&(U5=0),true))
预期:
(A5,2)
(left(A5,2)=39)
(A5<>3905)
(A5<>3908)
(A5<>3909)
(V5>0)
(T5=0)
(U5=0)
((left(A5,2)=39)&(A5<>3905)&(A5<>3908)&(A5<>3909),(V5>0)&(T5=0)&(U5=0),true)
(if((left(A5,2)=39)&(A5<>3905)&(A5<>3908)&(A5<>3909),(V5>0)&(T5=0)&(U5=0),true))
正则:/(?=(\((?:(?1)|[^()]*)*\)))/
题解:https://hiregex.com/r/D2iOm2/1
题样:https://hiregex.com/r/QgjFM4/1

4.练完上面的题

QQ找几个正则群加入进去,多多练习~

文文的博客

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

园长的牧歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值