今天讲正则表达式的一个使用技巧:怎么判断一个字符串既含有字母又含有数字。这在判断某个字符串是不是MPN时非常有用,因为货物编号MPN(Manufacturer part number)就符合这个模式,在搜索时经常要判断某个字符串是不是MPN。
正则表达式基础
首先,介绍一下本文所需要一些正则表达式的基础,如果你没有一点正则表达式的基础,学习起来可能会有点吃力,但是只要理解了本文所讲的基础,也很容易掌握。这里我们使用Python,用其他编程语言时正则表达式的语法差不多,但是要根据不同的编程语言的语法要求做相应的改变。在Python里面处理正则表达式的模块是re。
- 方括号表示字符集,除了连字符-外和反斜线\外在方括号里面的所有字符串都取其字面意思。反斜线用于指定特殊的字符比如空白\s,而连字符-如果出现在两个字符之间则表示范围,出现在最后则表示其字面意思,即匹配连字符本身。
比如[ABC]表示匹配A、B和C三个大写字母,[0-9]表示匹配0到9这个10个数字,而[a-z-]则表示匹配a到z的小写字母以及连字符-,依此类推。
-
>>> import re
-
-
>>> (r"[A-Z0-9-]+", "MPN123")
-
< object; span=(0, 6), match='MPN123'>
- (regex, string, flags)可用来判断某个字符串是否满足某个正则表达式。其中regex是正则表达式,string 是要匹配的字符串,flags则是匹配的参数,最常用的参数是,可以缩写为,表示匹配时忽略字符的大小写。另外建议在正则表达式之前加上原始字符串表示符r,那样看起来比较明了。
- 如果匹配则返回一个匹配对象,可以通过该匹配对象的group方法来获取匹配的值。
-
>>> (r"[A-Z0-9-]+", "MPN123").group()
-
'MPN123'
- 尖括号^匹配字符串开始,而美元符号$匹配字符串的结尾。
- 圆括号则匹配字符的组合,所有在圆括号内的字符串必须同时满足
-
>>> (r"(abc)[0-9]", "abc1")
-
< object; span=(0, 4), match='abc1'>
-
-
>>> (r"(abc)[0-9]", "bcd1") # 不匹配
- 现在难点来了,我们需要理解什么是先行断言(lookahead assertion)。先行断言就是在指判断某个模式是否匹配之前,需要先看看后面的模式是否匹配。其语法是A(?=B), 其含义为只有当模式B紧跟模式A时,才会匹配模式A:
举个例子:
-
>>> (r"[0-9]{4}(?=-01-01)", "2020-01-01")
-
< object; span=(0, 4), match='2020'>
-
-
>>> (r"[0-9]{4}(?=-01-01)", "2020-02-01")
-
# 年份后面跟的不是-01-01,不匹配
MPN正则表达式
好了,介绍了Python正则表达式的基础之后,进入本文的正题了,怎么判断一个字符串中只含有字母和数字,而且同时含有字母和数字呢。为了说明的方便,我们将符合这样要求的字符串称为MPN。
废话不多说,直接给结果:
-
>>> (r"^(?=[A-Z0-9]*[A-Z])(?=[A-Z0-9]*[0-9])", 'MPN100', )
-
< object; span=(0, 0), match=''>
这个正则表达式有点复杂,乍看有点懵,要理解它需要掌握几个关键点:
- 用尖括号^表示判断整个字符串是否是一个MPN,如果只想判断字符串是否含有MPN子串时,则可以用\b替换^,\b匹配子串或者单词的开始:
-
>>> (r"^(?=[A-Z0-9]*[A-Z])(?=[A-Z0-9]*[0-9])", "I'm an MPN100", )
-
# MPN是一个子串,不在字符串的开始,不匹配
-
-
>>> (r"\b(?=[A-Z0-9]*[A-Z])(?=[A-Z0-9]*[0-9])", "I'm an MPN100", )
-
< object; span=(7, 7), match=''>
-
# 用\b匹配子串
- [A-Z0-9]要求MPN中只能含有大写字母和数字,如果你允许MPN中有其他字符,可以将其加到方括号中。
- 是的缩写,说明该正则表达式既可以匹配大写字母,也可以匹配小写字母。如果你只想匹配大写字母,则需将省去。
- 先行断言可以有多个,它们是互相独立的,同时起作用,顺序没有关系。这里的先行断言要求后面既要有字母也要有数字。
- 需要注意的是先行断言本身是不占用任何字符的,它只要求后面的字符串符合某种要求,所以这里的匹配值是空字符串,不要误以为没有匹配成功。
举几个实际中的例子:
-
>>> (r"^(?=[A-Z0-9]*[A-Z])(?=[A-Z0-9]*[0-9])", "QE55LST7T", )
-
< object; span=(0, 0), match=''>
-
-
>>> (r"\b(?=[A-Z0-9]*[A-Z])(?=[A-Z0-9]*[0-9])", "Samsung QE55LST7T", )
-
< object; span=(8, 8), match=''>
-
-
>>> (r"\b(?=[A-Z0-9]*[A-Z])(?=[A-Z0-9]*[0-9])", "190198915818", )
-
# EAN是纯数字,不匹配
最后推荐两个Python正则表达式的常用网站:
- /wp-content/uploads/2019/03/
- /