import re #使用正则表达式来处理数据需要先调用re库(python默认安装)
var_str_list = ["+5.02 mm", "-5.02 mm", "1.2e6 MPa", "-1.e6 MPa", "100,000.01"]
print(var_str_list)
var_float_list = [float(re.sub("[^0-9\-.eE]","",var_str))
for var_str in var_str_list ]
[5.02, -5.02, 1200000.0, -1000000.0, 100000.01]
re.sub("[^0-9\-.eE]","",var_str)
"[^0-9\-.eE]"
函数 | 描述 | 操作实质 |
---|---|---|
findall | 返回包含所有匹配的字符段的list | 查找 |
search |
返回包含匹配的字符段的 Match object(后文介绍对象构成)
| 查找 |
split | 将字符串在符合匹配表达式的位置处分割,以list形式返回 | 替换 |
sub | 将字符串内匹配一处或者多处表达式的字段替换成自定义的字段 | 替换 |
re.findall("a","a , b , c")
re.search("a","a , b , c")
re.split(",","a , b , c")
re.sub(",","+","a , b , c")
['a']
<re.Match object; span=(0, 1), match='a'>
['a ', ' b ', ' c'] #格外注意这里的空格,实际中这里是容易出问题的地方
'a + b + c'
thisMatch = re.search("xyz","xyz , abc , xyz")
print(thisMatch.span())
print(thisMatch.string)
print(thisMatch.group())
(0, 3)
xyz , abc , xyz
xyz
函数 | 描述 | 操作实质 |
---|---|---|
finditer | 与findall返回匹配的字符段的list不同,这里返回的是可调用的iterator | 查找 |
fullmatch | 返回完全符合匹配的字符段的 Match object,注意这里是完全符合 | 查找 |
subn | 返回一个tuple,包含替换后的新字符串,同时给出替换发生的次数 | 替换 |
x=re.finditer("[a-zA-Z]","a, A")
for s in x:
print(s.span())
((0, 1)
(3, 4)
print(re.fullmatch("^hel{2}o world$","hello world"))
print(re.fullmatch("^hel{2}o world$","hello world!"))
<re.Match object; span=(0, 11), match='hello world'>
None
re.subn("\d","d","1 2 3")
('d d d', 3)
print(re.escape('https://www.xyz.org'))
https://www\.xyz\.org
元字符 | 描述 | 范例 | 范例解释 |
---|---|---|---|
[] | 一类字符的集合 | "[a-m]" | 目标字符为a-m中其中一个字母(包括a,m), 类似还可以写出"[3-9]",目标字符为3-9之间一个数字(包括3,9) |
\ | 表示开始一个特殊字符段或者用于转义 | "\d" | \d表示返回字符串中含有表示数字的字符, 这类特殊标记后文会详细介绍 |
. | 可以用于表示任意字符,换行(new line)符号例外 | "he..o" | 任何以he开始后面跟两个字符再加上o的组合均满足需求, 比如“hello”, “hexxo”等等 |
^ | 目标字符以此开始 | "^hello" | 任何以hello开始的字符串: re.findall("^hello", "hello world")会返回hello, 而re.findall("^hello", "world hello")会返回空 |
$ | 目标字符以此结束 | "world$" |
任何以world结束的字符段:
re.findall("world$", "hello world")会返回world
,而re.findall("world$", "world hello")会返回空 |
* | 之前的一个字段出现零次或者更多次 | "he.*o" | 任意字符(.)不出现或者重复出现很多次,“hello”,“helo”, “heo” 均符合要求。注意这里的小陷阱,“heldaffaxo”也是符合要求的, 因为是任意字符出现多次,并非指定字符出现零次或者多次, 换句话说,这里任何以he开口,o结尾的字符串均符合要求, 这在实际使用中及其常用 |
+ |
之前的一个字段出现一次或者更多次
| "he.+o" | 任意字符(.)至少出现一次,“hello”,“helo”均符合要求, “heo”不符合要求。如前分析,“heldaffaxo”也是符合要求的 |
? | 之前的一个字段出现零次或者一次 | "he.?o" | 任意字符(.)至多出现一次, “heo”,“helo”均符合要求, “hello”不符合要求。在这里“heldaffaxo”就不再符合要求了 |
{m,n} {n} | 之前字段重复出现m-n次(包括m,n) 之前字段重复出现n次 | "he.{2}o" | 任意字符(.)必须出现两次,“hello”符合要求, “helo”,“heo”不符合 要求。 与"he.*o"相比,其实实际上"he.{2}o"是在限制开头和结尾的 基础上加上了字符长度限制的硬性规定,这个实际中也较常用到, 比如检索学校数据库中以“A”开头,以“2021”结尾的所有学号 |
| | 或者 | "hello|world" | 不言自明 |
() | 群组(group) | ^(world|hello) | re.sub("(world|hello)","XY", "world world hello")返回'XY XY XY', ()内的字符串会作为一个整体参与后续运算, 换句话说()加上()内的东西在运算中等价于一个字符 |
*?, +?, ?? | 关闭*,+, ?的贪婪(greedy)模式 | <.*?> | 在*,+, ?后面在加上一个?可以关闭默认的贪婪模式, re.findall('<.*>','<a> b <c>')会返回整个字符串['<a> b <c>'], 而re.findall('<.*?>','<a> b <c>')仅仅返回['<a>', '<c>'] |
在正则表达式中以'\'开头具有特殊含义的字符组合
字符 | 具体描述 | 示例 | 示例解释 |
---|---|---|---|
\A | 若本字符后的字符段是对应字符串的开头则为对应match | "\Ahel" | re.findall("\Ahel","hello")返回['hello'], 而re.findall("\Ahel","xhello")返回为空 |
\b | 若本字符后的字符段是对应字符串的开头或者结尾则为对应match (此处r是确保字符串被当作raw string处理,缺失则无法正常识别) | r"llo\b" | re.findall(r"llo\b","hello")返回['hello'],而 re.findall(r"llo\b","hellox")则返回为空 |
\B | 若本字符后的字符段出现在字符串中,但是不在开头或者不在结尾则为对应match (此处r是确保字符串被当作raw string处理,缺失则无法正常识别) | r"\Blo"(不在开头) r"lo\B"(不在结尾) | re.findall(r"\Blo","hello")返回['lo']而 re.findall(r"\Blo","lohel")则返回为空 |
\Z |
若本字符后的字符段是对应字符串的结尾则为对应match
| r"llo\Z" | re.findall("lo\Z","hello")返回['lo'] |
\d | 返回字符串中字符为数字的部分 | "\d" | re.findall(r"\d","hi 2.2")返回['2', '2'] |
\D | 返回字符串中字符不是数字的部分 | "\D" | re.findall(r"\D","hi 2.2")返回['h', 'i', ' ', '.'] |
\s | 返回字符串中包含空格符的部分 | "\s" | re.findall("\s","hello world")返回[' '] |
\S | 返回字符串中不包含空格符的部分 | "\S" | re.findall("\S","hello world")返回 ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'] |
\w | 返回字符串中包含word的部分 (a-Z, 0-9以及下划线_) | "\w" | re.findall("\w","hi_you % /1.0")返回 ['h', 'i', '_', 'y', 'o', 'u', '1', '0'] |
\W | 返回字符串中不包含word的部分 (除a-Z, 0-9以及下划线_以外的字符) | "\W" | re.findall("\W","hi_you % /1.0")返回 [' ', '%', ' ', '/', '.'] |
集合(set) | 描述 | 示例解释 |
---|---|---|
[arn] | 找到字符段中存在 a , r , 或者 n 的一个字符 | |
[a-n] | 找到字符段中存在 a-n 之间的一个字符 | |
[^arn] | 找到字符段中除a , r , 或者 n 以外的一个其他字符,[^]操作非常实用 | |
[012] | 找到字符段中存在 0, 1, 或者 2 的一个数字字符 | |
[0-9] | 找到字符段中存在 0-9 之间的一个数字字符 | |
[0-1][0-9] | 找到字符段中两位的数字,第一位在0-1之间,第二位在0-9之间(实际就是00-19) | re.findall("[0-1][0-9]","12")返回['12'] re.findall("[0-1][0-9]","42")返回空 |
[a-zA-Z] | 找到字符段中存在 a-z, A-Z 之间的一个字符 | re.findall("[a-zA-Z]","aA")返回['a', 'A'] re.findall("[a-zA-Z]","42")返回空 |
[+] | 在集合(set)的符号([ ])中间,+, *, ., |, (), $,{} 都是没有特殊含义的 |
import re
txt = "+-rain 1.0-"
x = re.findall("[+-0-9]", txt)
print(x)
['+', '-', '.', '0', '-']
txt = "+-rain 1.0-"
x = re.findall("[+\-0-9]", txt)
print(x)
['+', '-', '1', '0', '-']
模块常量 | 调用方法 | 解释 |
---|---|---|
IGNORECASE | re.IGNORECASE 或简写为 re.I | 匹配中忽略大小写 |
ASCII | re.ASCII 或简写为 re.A | 保证 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配ASCII, 而不是Unicode |
DOTALL | re.DOTALL 或简写为 re.S | 匹配所有字符,包括换行符\n。注意默认模式下 . 是不能匹配行符\n的 |
MULTILINE | re.MULTILINE 或简写为 re.M | 多行模式,当某字符串中有换行符\n, 默认模式下是不支持换行符特性的,比如:行开头 和 行结尾,而多行模式下是支持匹配行开头的 默认模式下它只能匹配字符串的开头; 而在多行模式下,它还可以匹配 换行符\n后面的字符。 单行模式下它两效果一致,多行模式下\A不能识别\n |
VERBOSE | re.VERBOSE 或简写为 re.X | 详细模式,可以在正则表达式中加注释, 可以说非常非常有用! |
a = re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")
emails = ["Aacb111.111@qq.com", "11D1-1d11@163.com", "111_1d1d1@py.p-y.py.com","d?@sina.com","12d", ".111111@qq.com"]
regexPattern = re.compile(r"""^[0-9a-zA-z][0-9a-zA-z_.\-]+ # 邮箱名称可以包含数字,字母和下划线_横线-和点.,且必须以字母或数字开始
@ # 标准邮箱符号
(([0-9a-zA-z\-]+).)+ # 子域名1
[0-9a-zA-z\-]+$ # 高级域名""", re.X)
for email in emails:
print(re.fullmatch(regexPattern, email))
<re.Match object; span=(0, 18), match='Aacb111.111@qq.com'>
<re.Match object; span=(0, 17), match='11D1-1d11@163.com'>
<re.Match object; span=(0, 23), match='111_1d1d1@py.p-y.py.com'>
None
None
None