写点什么

正则表达式.05 - 匹配模式

用户头像
insight
关注
发布于: 2021 年 03 月 10 日
正则表达式.05 - 匹配模式

所谓匹配模式,指的是正则中一些改变元字符匹配行为的方式。


常见的匹配模式有 4 种,分别是

  • 不区分大小写模式:它可以让整个正则或正则中某一部分进行不区分大小写的匹配。

  • 点号通配模式:改变 . 的匹配行为,,让其可以匹配任何字符,包括换行。

  • 多行模式:使 ^$ 能匹配上每行的开头或结尾

  • 注释模式:可以在正则中添加注释,让正则变得更容易阅读和维护。


使用匹配模式的方法

模式修饰符是通过 (? 模式标识) 的方式来表示的。 我们只需要把模式修饰符放在对应的正则前,就可以使用指定的模式了。


需要注意的是,这里的“模式”对应的是英文中的 mode,而不是 pattern。有些地方会把正则表达式 pattern 也翻译成模式,你在网上看到的技术文章中讲的正则模式,有可能指的是正则表达式本身,这一点你需要注意区别。


不区分大小写模式(Case-Insensitive)

不区分大小写模式可以用来忽视单词的大小写。


修饰符为:(?i)


由于不分大小写的英文是 Case-Insensitive,那么对应的模式标识就是 I 的小写字母 i,所以不区分大小写的 cat 就可以写成 (?i)cat


通过修饰符指定匹配模式的方式,在大部分编程语言中都是可以直接使用的,但在 JS 中我们需要使用 /regex/i 来指定匹配模式。在编程语言中通常会提供一些预定义的常量,来进行匹配模式的指定。比如 Python 中可以使用 re.IGNORECASEre.I ,来传入正则函数中来表示不区分大小写

>>> import re>>> re.findall(r"cat", "CAT Cat cat", re.IGNORECASE)['CAT', 'Cat', 'cat']
复制代码

不区分大小写模式的要点:

  1. 不区分大小写模式的指定方式,使用模式修饰符 (?i);

  2. 修饰符如果在括号内,作用范围是这个括号内的正则,而不是整个正则;

  3. 使用编程语言时可以使用预定义好的常量来指定匹配模式。


点号通配模式(Dot All)

正则中,英文的点(.)可以匹配上任何符号,但不能匹配换行。当我们需要匹配真正的“任意”符号的时候,需要使用 [\s\S] 或 [\d\D] 或 [\w\W] 等。为了简洁自然,正则中提供了一种模式,让英文的点(.)可以匹配上包括换行的任何字符。这个模式就是点号通配模式,有很多地方把它称作单行匹配模式,但这么说容易造成误解,毕竟它与多行匹配模式没有联系。


单行的英文表示是 Single Line,修饰符是 :(?s)


需要注意的是,JavasScript 不支持此模式,那么我们就可以使用前面说的[\s\S]等方式替代。在 Ruby 中则是用 Multiline,来表示点号通配模式(单行匹配模式),我猜测设计者的意图是把点(.)号理解成“能匹配多行”。

多行匹配模式(Multiline)

通常情况下,^匹配整个字符串的开头,$ 匹配整个字符串的结尾。多行匹配模式改变的就是 ^$ 的匹配行为。


它使 ^ 和 $ 能匹配上每行的开头或结尾


模式修饰符号为:(?m)


作用:在处理日志时,如果日志以时间开头,有一些日志打印了堆栈信息,占用了多行,我们就可以使用多行匹配模式,在日志中匹配到以时间开头的每一行日志。


值得一提的是,正则中还有 \A 和 \z(Python 中是 \Z) 这两个元字符容易混淆,\A 仅匹配整个字符串的开始,\z 仅匹配整个字符串的结束,在多行匹配模式下,它们的匹配行为不会改变,如果只想匹配整个字符串,而不是匹配每一行,用这个更严谨一些。

注释模式(Comment)

在实际工作中,正则可能会很复杂,这就导致编写、阅读和维护正则都会很困难。我们在写代码的时候,通常会在一些关键的地方加上注释,让代码更易于理解。很多语言也支持在正则中添加注释,让正则更容易阅读和维护,这就是正则的注释模式。


模式修饰符号:(?#注释内容)


比如我们可以把单词重复出现一次的正则 (\w+) \1 写成下面这样,这样的话,就算不是很懂正则的人也可以通过注释看懂正则的意思。

(\w+)(?#word) \1(?#word repeat again)
复制代码

在很多编程语言中也提供了 x 模式来书写正则,也可以起到注释的作用。


Python3 的例子

import re
regex = r'''(?mx) # 使用多行模式和x模式^ # 开头(\d{4}) # 年(\d{2}) # 月$ # 结尾'''
re.findall(regex, '202006\n202007')# 输出结果 [('2020', '06'), ('2020', '07')]
复制代码

需要注意的是在 x 模式下,所有的换行和空格都会被忽略。为了换行和空格的正确使用,我们可以通过把空格放入字符组中,或将空格转义来解决换行和空格的忽略问题。

regex = r'''(?mx)^          # 开头(\d{4})    # 年[ ]        # 空格(\d{2})    # 月$          # 结尾'''
re.findall(regex, '2020 06\n2020 07')# 输出结果 [('2020', '06'), ('2020', '07')]
复制代码


用户头像

insight

关注

不要混淆行动与进展、忙碌与多产。 2018.11.17 加入

永远都是初学者

评论

发布
暂无评论
正则表达式.05 - 匹配模式