Files
ailearning/docs/da/067.md
2020-10-19 21:08:55 +08:00

271 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 正则表达式和 re 模块
## 正则表达式
[正则表达式](http://baike.baidu.com/view/94238.htm)是用来匹配字符串或者子串的一种模式,匹配的字符串可以很具体,也可以很一般化。
`Python` 标准库提供了 `re` 模块。
In [1]:
```py
import re
```
## re.match & re.search
`re` 模块中, `re.match``re.search` 是常用的两个方法:
```py
re.match(pattern, string[, flags])
re.search(pattern, string[, flags])
```
两者都寻找第一个匹配成功的部分,成功则返回一个 `match` 对象,不成功则返回 `None`,不同之处在于 `re.match` 只匹配字符串的开头部分,而 `re.search` 匹配的则是整个字符串中的子串。
## re.findall & re.finditer
`re.findall(pattern, string)` 返回所有匹配的对象, `re.finditer` 则返回一个迭代器。
## re.split
`re.split(pattern, string[, maxsplit])` 按照 `pattern` 指定的内容对字符串进行分割。
## re.sub
`re.sub(pattern, repl, string[, count])``pattern` 匹配的内容进行替换。
## re.compile
`re.compile(pattern)` 生成一个 `pattern` 对象,这个对象有匹配,替换,分割字符串的方法。
## 正则表达式规则
正则表达式由一些普通字符和一些元字符metacharacters组成。普通字符包括大小写的字母和数字而元字符则具有特殊的含义
| 子表达式 | 匹配内容 |
| --- | --- |
| `.` | 匹配除了换行符之外的内容 |
| `\w` | 匹配所有字母和数字字符 |
| `\d` | 匹配所有数字,相当于 `[0-9]` |
| `\s` | 匹配空白,相当于 `[\t\n\t\f\v]` |
| `\W,\D,\S` | 匹配对应小写字母形式的补 |
| `[...]` | 表示可以匹配的集合,支持范围表示如 `a-z`, `0-9` 等 |
| `(...)` | 表示作为一个整体进行匹配 |
| ¦ | 表示逻辑或 |
| `^` | 表示匹配后面的子表达式的补 |
| `*` | 表示匹配前面的子表达式 0 次或更多次 |
| `+` | 表示匹配前面的子表达式 1 次或更多次 |
| `?` | 表示匹配前面的子表达式 0 次或 1 次 |
| `{m}` | 表示匹配前面的子表达式 m 次 |
| `{m,}` | 表示匹配前面的子表达式至少 m 次 |
| `{m,n}` | 表示匹配前面的子表达式至少 m 次,至多 n 次 |
例如:
* `ca*t 匹配: ct, cat, caaaat, ...`
* `ab\d|ac\d 匹配: ab1, ac9, ...`
* `([^a-q]bd) 匹配: rbd, 5bd, ...`
## 例子
假设我们要匹配这样的字符串:
In [2]:
```py
string = 'hello world'
pattern = 'hello (\w+)'
match = re.match(pattern, string)
print match
```
```py
<_sre.SRE_Match object at 0x0000000003A5DA80>
```
一旦找到了符合条件的部分,我们便可以使用 `group` 方法查看匹配的部分:
In [3]:
```py
if match is not None:
print match.group(0)
```
```py
hello world
```
In [4]:
```py
if match is not None:
print match.group(1)
```
```py
world
```
我们可以改变 string 的内容:
In [5]:
```py
string = 'hello there'
pattern = 'hello (\w+)'
match = re.match(pattern, string)
if match is not None:
print match.group(0)
print match.group(1)
```
```py
hello there
there
```
通常,`match.group(0)` 匹配整个返回的内容,之后的 `1,2,3,...` 返回规则中每个括号(按照括号的位置排序)匹配的部分。
如果某个 `pattern` 需要反复使用,那么我们可以将它预先编译:
In [6]:
```py
pattern1 = re.compile('hello (\w+)')
match = pattern1.match(string)
if match is not None:
print match.group(1)
```
```py
there
```
由于元字符的存在,所以对于一些特殊字符,我们需要使用 `'\'` 进行逃逸字符的处理,使用表达式 `'\\'` 来匹配 `'\'`
但事实上,`Python` 本身对逃逸字符也是这样处理的:
In [7]:
```py
pattern = '\\'
print pattern
```
```py
\
```
因为逃逸字符的问题,我们需要使用四个 `'\\\\'` 来匹配一个单独的 `'\'`
In [8]:
```py
pattern = '\\\\'
path = "C:\\foo\\bar\\baz.txt"
print re.split(pattern, path)
```
```py
['C:', 'foo', 'bar', 'baz.txt']
```
这样看起来十分麻烦,好在 `Python` 提供了 `raw string` 来忽略对逃逸字符串的处理,从而可以这样进行匹配:
In [9]:
```py
pattern = r'\\'
path = r"C:\foo\bar\baz.txt"
print re.split(pattern, path)
```
```py
['C:', 'foo', 'bar', 'baz.txt']
```
如果规则太多复杂,正则表达式不一定是个好选择。
## Numpy 的 fromregex()
In [10]:
```py
%%file test.dat
1312 foo
1534 bar
444 qux
```
```py
Writing test.dat
```
```py
fromregex(file, pattern, dtype)
```
`dtype` 中的内容与 `pattern` 的括号一一对应:
In [11]:
```py
pattern = "(\d+)\s+(...)"
dt = [('num', 'int64'), ('key', 'S3')]
from numpy import fromregex
output = fromregex('test.dat', pattern, dt)
print output
```
```py
[(1312L, 'foo') (1534L, 'bar') (444L, 'qux')]
```
显示 `num` 项:
In [12]:
```py
print output['num']
```
```py
[1312 1534 444]
```
In [13]:
```py
import os
os.remove('test.dat')
```