re正则表达式、shutil、ConfigParser、xml
一、re
- 正则元字符和语法:
语法 | 说明 | 表达式 | 完全匹配字符 |
字符 | |||
一般字符 | 匹配自身 | abc | abc |
. | 匹配除换行符“\n”外,任意一个字符 | a.c | abc |
\ | 转义字符,将特殊字符转义为本身 |
a\.c a\\c |
a.c a\c |
[...] |
匹配字符集任意一个字符,或者“-”表示一个集合范围 如:[a-zA-Z0-9]匹配范围中任意一个字符;或者[^] 匹配否定,对括号中的内容取反。 |
[abc]efg |
aefg befg cefg |
预定义字符集 | |||
\d | 数字:[0-9] | a\dc | a1c |
\D | 非数字:[^\d] | a\Dc | abc |
\s | 空白字符:[<空格>\t\r\n\f\v] | a\sc | a c |
\S | 非空白字符:[^\s] | a\Sc | abc |
\w | 字符:[a-zA-Z0-9_] | a\wc | abc |
\W | 非单词字符:[^\w] | a\Wc | a c |
数量词 | |||
* | 匹配前一个字符0次或无数次 | a*b |
aab ab b |
+ | 匹配前一个字符1次或无数次 | a+b |
aab aaaab |
? | 匹配前一个字符0次或1次 | a?b |
b ab |
{m} | 匹配前一个字符m次 | a{2}c | aac |
{m,n} |
匹配前一个字符m次到n次。m与n可以省略 如果省略m,表示0次到n次;省略n表示从m次到 无数次 |
a{1,2}c |
ac aac |
*? +? ?? {m,n}? |
使*、+、?、{m,n}变为非贪婪模式 | 见后文 | |
边界匹配 | |||
^ | 匹配字符串开头 | ^abc | abc |
$ | 匹配字符串结尾 | abc$ | abc |
\A | 仅匹配字符串开头 | \Aabc | abc |
\Z | 仅匹配字符串结尾 | abc\Z | abc |
\b |
匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er” |
ab\b | ab |
\B |
匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er” |
ab\Bc | abc |
逻辑与分组 | |||
| |
代表左右表达式任意匹配一个。 它总是先匹配左边的,一旦匹配成功,则跳过右边表达式。 如果|没有被包含在()中,他的范围将是整个表达式。 |
abc|def |
abc def |
() |
被括号括起来的表达式将视为分组。 从表达式左边开始,每遇到一个分组的左括号“(“,编号+1 分组表达式作为一个整体,可以后接数量词。表达式中|仅在分组中生效。 |
(abc){2} (abc|bcd) |
abcabc abc |
(?P<name>...) | 分组,除了原有编号外,再指定一个别名。group(1)=group(name) | (?P<id>abc) | abc |
(?P=name)引用别名为name的分组匹配到的字符串(?P<id>123)abc(?P=id)123abc123 |
-
数量词的贪婪模式与非贪婪模式
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。
-
反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
- re相关匹配方法
- match
match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
1 import re 2 3 text="the Attila the Hun show" 4 m = re.match(".",text) 5 print(m.group()) #"t" 或者group(0)取得匹配所有结果 6 7 m = re.match("(.)(.)(.)",text) 8 print(m.group(0)) #"the" 9 10 #分组 11 print(m.group(1,2,3)) #(‘t‘,‘h‘,‘e‘) 匹配后得分组 12 13 #将正则编译成Pattern对象 14 pattern = re.compile(".") 15 m = pattern.match(text) 16 print(m.group()) #‘t‘
2. search
search, 浏览整个字符串去匹配第一个,未匹配成功返回None
1 import re 2 text = "Example 3:there is 1 date 11/5/2016 in here" 3 m = re.search("(\d{1,2})/(\d{1,2})/(\d{2,4})",text) 4 print(m.group(1),m.group(2),m.group(3))# 11 5 2016
3. sub
替换匹配成功的指定位置字符串
1 import re 2 # sub(pattern, repl, string, count=0, flags=0) 3 # pattern: 正则模型 4 # repl : 要替换的字符串或可执行对象 5 # string : 要匹配的字符串 6 # count : 指定匹配个数 7 # flags : 匹配模式 8 text = "you‘re no fun anymore fun" 9 m = re.sub("fun","entertaining",text,2) 10 print(m) 11 # "you‘re no entertaining anymore entertaining"
4. spilt
根据正则匹配分隔字符串
import re # split(pattern, string, maxsplit=0, flags=0) # pattern: 正则模型 # string : 要匹配的字符串 # maxsplit:指定分割个数 # flags : 匹配模式 # 无分组 origin = "hello alex bcd alex lge alex acd 19" r = re.split("alex", origin, 1) print(r) #["hello","bcd alex lge alex acd 19"] # 有分组 origin = "hello alex bcd alex lge alex acd 19" r1 = re.split("(alex)", origin, 1) print(r1) # ["hello","alex","bcd alex lge alex acd 19"] r2 = re.split("(al(ex))", origin, 1) print(r2) # ["hello","alex","ex","bcd alex lge alex acd 19"]
5. findall
获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
空的匹配也会包含在结果中
1 # 无分组 2 origin = "hello alex bcd abcd lge acd 19" 3 r = re.findall("a\w+",origin) 4 print(r) # ["alex","abcd","acd"] 5 6 # 有分组 7 origin = "hello alex bcd abcd lge acd 19" 8 r = re.findall("a((\w*)c)(d)", origin) 9 print(r) # 匹配两个字符串"abcd"&"acd"先将匹配最外层分组的元素放入元祖#中,再将内层分组匹配的元素放入元祖中结果[("bc","b","d"),("c","","d")]
IP: ^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$ 手机号: ^1[3|4|5|8][0-9]\d{8}$ 邮箱: [a-zA-Z0-9_-][email protected][a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+
二、shutil
高级文件、文件夹、压缩包处理模块
- 将文件内容拷贝到另一个文件
shutil.copyfileobj(fsrc, fdst[, length])
1 import shutil 2 shutil.copyfileobj(open(‘old.xml‘,‘r‘), open(‘new.xml‘, ‘w‘))
2. 拷贝文件
shutil.copyfile(src, dst)
1 shutil.copyfile(‘f1.log‘, ‘f2.log‘)
3. 仅拷贝权限。内容、组、用户均不变
shutil.copymode(src, dst)
1 shutil.copymode(‘f1.log‘, ‘f2.log‘)
4. 仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copystat(src, dst)
1 shutil.copystat(‘f1.log‘, ‘f2.log‘)
5. 拷贝文件和权限
shutil.copy(src, dst)
1 shutil.copy(‘f1.log‘, ‘f2.log‘)
6. 拷贝文件和状态信息
shutil.copy2(src, dst)
1 shutil.copy2(‘f1.log‘, ‘f2.log‘)
7. 递归的去拷贝文件夹
shutil.ignore_patterns(*patterns) 忽略某些格式文件
shutil.copytree(src, dst, symlinks=False, ignore=None)
1 import shutil 2 shutil.copytree(‘folder1‘, ‘folder2‘, ignore=shutil.ignore_patterns(‘*.pyc‘, ‘tmp*‘))
1 import shutil 2 shutil.copytree(‘f1‘, ‘f2‘, symlinks=True, ignore=shutil.ignore_patterns(‘*.pyc‘, ‘tmp*‘))
8. 递归的去删除文件
shutil.rmtree(path[, ignore_errors[, onerror]])
1 import shutil 2 shutil.rmtree(‘folder1‘)
9. 递归的去移动文件,它类似mv命令,其实就是重命名。
shutil.move(src, dst)
1 import shutil 2 shutil.move(‘folder1‘, ‘folder3‘)
10. 创建压缩包并返回文件路径,例如:zip、tar
shutil.make_archive(base_name, format,...) 这个功能只能压缩一个文件夹
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,如:www =>保存至当前路径如:/Users/lcy/www =>保存至/Users/lcy/
- format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
#将 /Users/lcy/Downloads/test 下的文件打包放置当前程序目录 import shutil ret = shutil.make_archive("www", ‘gztar‘, root_dir=‘/Users/lcy/Downloads/test‘) #将 /Users/lcy/Downloads/test 下的文件打包放置 /Users/lcy/目录 import shutil ret = shutil.make_archive("/Users/lcy/www", ‘gztar‘, root_dir=‘/Users/lcy/Downloads/test‘)
附加:ZipFile 和 TarFile一般用这个较多
1 import zipfile 2 3 # 压缩 4 z = zipfile.ZipFile(‘laxi.zip‘, ‘w‘) #创建一个压缩包 5 z.write(‘a.log‘) 6 z.write(‘data.data‘) 7 z.close() 8 # 解压 9 z = zipfile.ZipFile(‘laxi.zip‘, ‘r‘) 10 z.extractall() 11 z.close()