学习辅助网站
正则表达式的练习使用了如下两个网站:
1.https://regexr.com/ 在线验证工具,用来查看正则表达式匹配的结果
2.https://alf.nu/RegexGolf 练习网站,写出的正则表达式需满足左侧列匹配成功、右侧列匹配不成功的条件,下面的题目均出自此网站
题目中学习
Q1.Warmup
观察:匹配包含’foo’的字符串,‘foo’可在开头也可在中间和末尾
思路:0个及以上字符后面接’foo’
写法:
\w*foo
(只写foo也可通过)
注释:
语法 | 含义 |
---|---|
\w | 单字字符[a-zA-Z0-9] |
* | 匹配前一个字符0次或无限次 |
一般字符(本例中foo) | 匹配自身 |
Q2.Anchors
观察:匹配以’ick’结尾的字符串
思路:限制字符串的结尾位置为’ick’
写法:
ick$
注释:
语法 | 含义 |
---|---|
$ | 匹配字符串末尾;多行模式中匹配每行的末尾 |
Q3.It never ends
观察:以’fu’结尾,但用’u’就足以区分,但题目要求不能使用’$’
思路:寻找其他能代替’$'使用的方法
写法1:
u\b
注释:
语法 | 含义 |
---|---|
\b | 匹配这样的位置:它的前一个字符和后一个字符不全是\w |
\B | 与\b情况相反,即前后均为\w |
此处学习了此篇文章
实际使用一下:
①使用\b:匹配到的是后面不是字母或数字的r
②使用\B:匹配到的是前后均是字母或数字的r
写法2:
u(?!\w)
u(?!.)
注释:
语法 | 含义 |
---|---|
(?!..) | 之后的字符需要不匹配表达式 |
(?=…) | 之后的字符需要匹配表达式 |
. | 除换行符\n之外的字符 |
u(?!\w)的含义即为:u字母后面为非字母(字符串末尾符合条件,因此匹配成功)
u(?!.)的含义即为:u字母后面为换行符之外的字符
实际使用一下:
① (?!..):匹配后面不是…处内容的a
后面不是b的a:
后面不是字母或数字的a:
② a(?=\w)
后面是字母或数字的a:
后面是c的a
Q4.Ranges
观察:
①均由abcdef6个字母组成,没有其他字母
②字符串长度在4-6
思路:
限制字符串长度为4-6直接,且字符由字母a-f组成
写法:
[a-f]{4,6}
注释:
语法 | 含义 |
---|---|
[…] | 字符集,对应位置可以是字符集中任意字符,可给出范围(如[a-c]),也可逐个列出(如[abc]);[^abc]则表示不是abc的字符 |
{m,n} | 匹配前一个字符m至n次(左右边界均包含),如果m省略则为0-n次,若n省略则为m至无穷次 |
实际使用一下:
[…]:
[…]{m,n}:
此问题如果没有字符串长度限制呢?
可以写:^[a-f]+$
语法 | 含义 |
---|---|
^ | 匹配字符串开头,多行模式匹配每行开头 |
+ | 匹配前一个字符一次或无限次 |
$ | 匹配字符串末尾,多行模式匹配每行末尾 |
Q5.Backrefs
观察:前三个字符在后面又重复出现了一次,两次中间可以隔0个及以上的字符
例如,allochirally,anticovenanting
思路:使用分组,取前三个字符为组,在后面的位置匹配到这一组
写法:
(...).*\1
注释:
语法 | 含义 |
---|---|
(…) | 括起来的表达式作为分组,编号从1开始 |
\1 | \number引用编号为<number>的分组匹配到的字符串 |
实际使用一下:
这里发现并不是符合\d都算匹配,而是需要和第一次匹配到的完全一致。
Q6.Abba
观察:这一题是右侧列存在规律,字符串中包含abba型的部分,那么左侧列的条件是不包含abba型的子串
思路:abba型的写法,通过上一题的学习,可以写为:(.)(.)\2\1,再使用(?!..)使字符串不匹配表达式才可匹配上,再考虑细节,abba前可以有字符,加上.*
写法:
^(?!.*(.)(.)\2\1)
注释:
语法 | 含义 |
---|---|
^ | 匹配字符串开头 |
(?!..) | 之后的字符不符合…的条件 |
.* | 除换行符外的字符重复0次及以上 |
(.)(.)\2\1 | 两个分组,每组一个除换行符之外的字符,然后重复第二组,再重复第一组,即abba型 |
Q7.A man, a plan
观察:左侧列均为回文,正序和逆序相同
思路:题目中写"You’re allowed to cheat a little."那我们就来偷个懒,用上一题中的abba式
写法:
^(.)(.).*\2\1$
注释:
这里只限制了第一个字符和最后一个字符相同,第二个字符和倒数第二个字符相同,但已经足够和右侧列区分开
Q8.Prime
观察:
左侧列x的个数为2, 3, 5, 7, 9, …
右侧列x的个数为4, 6, 8, 10, 12, …
思路:
右侧列均为大于2的偶数,规则比较单一,先写出右侧的规则,再使用(?!..)使其不满足此规则
写法:
^(?!(xx+)\1+$)
注释:
语法 | 含义 |
---|---|
+ | 匹配前面的子表达式一次或多次 |
^(?!(xx+)\1+$):xx+表示两个及以上的x
^(?!(xx+)\1+$):两个及以上的x重复了一次,满足了双数个x,且大于等于4
^(?!(xx+)\1+$):不满足上述条件,则为2个x,以及奇数个x,符合左侧列特征
匹配双数个x:
匹配大于等于3的单数个x:
Q9.Four
观察:左侧列均有字母出现了4次,且每次的间隔都为1个字符
思路:使用分组,定义一个组,再重复三次,中间隔一个字符
写法:
(.).\1.\1.\1
(.)(.\1){3} #精简一下
注释:
(.)(.\1){3}:定义一个字符的分组
(.)(.\1){3}:一个字符+分组1的内容
(.)(.\1){3}:重复三次(.\1)
Q10.Order
观察:左侧列的字符串内部均按照字母的顺序升序排列
思路:不是很好写,题目说明中写了cheat,也没有想出来,以下为网上看到的解法
写法1:
^[a-e]*[f-z]*$
注释:
限制了前面是a-f中的字母, 后面是f-z中的字母,恰好可以满足
写法2:
^.{5}[^e]?$
注释:
大神观察到了左侧列的长度均为5或6,限制长度后右侧只有一个字符串"oriole"匹配到了,且末尾是e,而左侧没有末尾是e的,因此又限制了末尾不是e,完成,实在是厉害。
Q11.Triples
观察:左侧列均为3的倍数
思路:没想出来,网上找的答案,不知道是不是自己水平不够,感觉这种规律没有什么意义
写法:
00($|3|6|9|12|15)|4.2|.1.+4|55|.17