Regular expression
定义
来自维基百科正则表达式。在理论计算机科学和形式语言理论中,正则表达式是定义搜索模式的一串字符。这种模式通常用于搜索or搜索并替换操作。
通常我们用于网络数据提取、指定文本查找是否含有特定的特征词及位置。在编辑器中广泛应用,如AS、Xcode、Sublime等。
换句话说,正则表达式就是记录文本规则的代码。
特殊字符
^ 为匹配输入字符串的开始位置
$ 为匹配输入字符串的结束位置
^[0-9]+mei$
[0-9]+匹配多个数字,[0-9]匹配单个数字,+匹配一个或者多个
mei$匹配字母mei并以mei结尾
() 表示一个子表达式的开始和结束位置, 如常用的 (.*?)
. 匹配除换行符之外的任意单个字符
*匹配前面子表达式零次或多次
+匹配前面子表达式1次或多次
?匹配前面的子表达式0次或1次
{}标记限定符表达式的开始和结束
|两项之间选其一
[]标记一个中括号表达式的开始和结束
\将下一个标记为或特殊字符、或原义字符、或八进制转义符。如’\n‘表示换行符,‘\ (’匹配(
普通字符
\d匹配一个数字字符,等价于[0-9]
\D匹配一个非数字字符,等价于 [^0-9]。
\s匹配空白符号,只可以匹配一个空格、制表符\t、回车符\r、换页符\n,不可以匹配自己输入的多个空格
\S匹配任何非空白字符
\w匹配包括下划线的任何单词字符, 等价于[A-Za-z0-9_]
\W匹配任何非单词字符,等价于[^A-Za-z0-9_]
\b匹配单词的开始或结束
定位符
^ 匹配输入字符串的开始位置。如果设置了 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置
也匹配 ‘\n’ 或 ‘\r’ 之前的位置
\b 匹配一个单词边界,也就是指单词和空格间的位置
🌰:
# ^
str1 = "hello world"
# pattern1 = "^world"
# # pattern2 = "^hello"
# print(re.sub(pattern1, "meipei", str1))
# $
# pattern3 = "world$"
# # pattern4 = "hello$"
# print(re.sub(pattern3, "meipai", str1))
# ^ $
# str_qq = "1019350030"
# pattern5 = "^\d{5,12}$"
# print(re.match(pattern5, str_qq).string)
# \b 单词边界 https://blog.csdn.net/uvyoaa/article/details/80854459
# str_b = "rhythm schoolshape technology rhythmtechnology school language"
# pattern_b = "rhythm"
# # pattern_b = r"\brhythm\b"
# print(re.findall(pattern_b, str_b))
# 表示字母数字与非字母数字的边界, 非字母数字与字母数字的边界
# print(re.split('123', '==123!! abc123. 123. 123abc. 123'))
# print(re.split('123\\b', '==123!! abc123. 123. 123abc. 123'))
限定符
*匹配前面子表达式零次或多次
+匹配前面子表达式1次或多次
?匹配前面的子表达式0次或1次
{n} 重复n次
{n,} 重复n次 or 更多次
{n,m} 重复n次到m次
🌰:
# * ? + {n,m}
# print(re.match(r'meipai*', "meipaimeipai").group())
# print(re.match(r'\w?', "meipai").group())
# print(re.match(r'meipai+', "meipai").group())
# print(re.match(r'meipai{3,5}', "meipai"))
参数flags
re.I IGNORECASE 忽略大小写的匹配模式
re.M MULTILINE 多行模式,改变^和$的行为。不仅仅在整个字符串的开头和结尾匹配
re.S DOTALL. 此模式下‘.’的匹配不受限制,可匹配任何字符,包括换行符,也就是默认是不匹配换行符的
re.X VERBOSE,冗余模式, 此模式忽略正则表达式中的空白和#号的注释
🌰:
# re.I re.M re.S re.X
# str_i = "meipai!"
# re_c_i = re.compile("meipai!", re.I)
# print(re_c_i.match(str_i).group())
# re.M
# str_m = "meitu line\nmeipai line\njayden line"
# re_not_m = re.compile(r'^\w+')
# print(re_not_m.findall(str_m))
#
# re_h_m = re.compile(r'^\w+', re.M)
# print(re_h_m.findall(str_m))
# re.S
# str_s = '''meitu line
# meipai line
# jayden line
# '''
# re_not_s = re.compile('.+')
# print(re_not_s.findall(str_s))
#
# re_h_s = re.compile('.+', re.S)
# print(re_h_s.findall(str_s))
# re.X
re_email = re.compile("[\w+\.]+@[a-zA-Z\d]+\.(com|cn|net)")
re_email_h_X = re.compile("""[\w+\.]+ # 匹配@符前的部分
@ # @符
[a-zA-Z\d]+ # 邮箱类别
\.(com|cn|net) # 邮箱后缀 """, re.X)
贪婪和非贪婪
贪婪模式是尽可能多的匹配字符串,Python默认为贪婪模式。 非贪婪模式是尽可能少的匹配字符串。
🌰:
str_jin = "#hello#world#"
print(re.match("#.*#", str_jin)) # 贪婪模式 输出 #hello#world#
print(re.match("#.*?#", str_jin)) # 非贪婪模式 输出 #hello#
从上面例子可以看出,在贪婪匹配中:
"#.*#"
, 它将会匹配最长的以#开始,以#结束的字符串。
"#.*?#"
,它将会匹配最短的以#开始,以#结束的字符串。
给出的限定符都可以被转化为非贪婪匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。