未验证 提交 4192fc7f 编写于 作者: K Kitty Du 提交者: GitHub

Update 8.3.md

措辞小改,表格小调
上级 e1673d3c
# regex 和 python # Regex 和 python
> 原文:[https://www.textbook.ds100.org/ch/08/text_re.html](https://www.textbook.ds100.org/ch/08/text_re.html) > 原文:[https://www.textbook.ds100.org/ch/08/text_re.html](https://www.textbook.ds100.org/ch/08/text_re.html)
``` ```python
# HIDDEN # HIDDEN
# Clear previously defined variables # Clear previously defined variables
%reset -f %reset -f
...@@ -13,7 +13,7 @@ os.chdir(os.path.expanduser('~/notebooks/08')) ...@@ -13,7 +13,7 @@ os.chdir(os.path.expanduser('~/notebooks/08'))
``` ```
``` ```python
# HIDDEN # HIDDEN
import warnings import warnings
# Ignore numpy dtype warnings. These warnings are caused by an interaction # Ignore numpy dtype warnings. These warnings are caused by an interaction
...@@ -42,13 +42,13 @@ pd.set_option('precision', 2) ...@@ -42,13 +42,13 @@ pd.set_option('precision', 2)
``` ```
在本节中,我们将使用内置的`re`模块在 python 中介绍 regex 的用法。因为我们只介绍了一些最常用的方法,所以您也可以参考[有关`re`模块](https://docs.python.org/3/library/re.html)的官方文档 在本节中,我们将介绍python内置的`re`模块中 regex 的用法。因为我们只介绍了一些最常用的方法,所以您也可以参考[有关`re`模块的官方文档](https://docs.python.org/3/library/re.html)
## `re.search`[¶](#re.search) #### `re.search`[](#re.search)
`re.search(pattern, string)``string`中的任意位置搜索 regex`pattern`的匹配项。如果找到模式,则返回一个 TruthyMatch 对象;如果没有,则返回`None` `re.search(pattern, string)``string`中的任意位置搜索 regex`pattern`的匹配项。如果找到模式,则返回一个 TruthyMatch 对象;如果没有,则返回`None`
``` ```python
phone_re = r"[0-9]{3}-[0-9]{3}-[0-9]{4}" phone_re = r"[0-9]{3}-[0-9]{3}-[0-9]{4}"
text = "Call me at 382-384-3840." text = "Call me at 382-384-3840."
match = re.search(phone_re, text) match = re.search(phone_re, text)
...@@ -60,9 +60,9 @@ match ...@@ -60,9 +60,9 @@ match
<_sre.SRE_Match object; span=(11, 23), match='382-384-3840'> <_sre.SRE_Match object; span=(11, 23), match='382-384-3840'>
``` ```
虽然返回的 match 对象有各种有用的属性,但我们最常用的是`re.search`来测试模式是否出现在字符串中。 虽然返回的 match 对象有各种有用的属性,但我们最常用`re.search`来测试模式是否出现在字符串中。
``` ```python
if re.search(phone_re, text): if re.search(phone_re, text):
print("Found a match!") print("Found a match!")
...@@ -73,7 +73,7 @@ Found a match! ...@@ -73,7 +73,7 @@ Found a match!
``` ```
``` ```python
if re.search(phone_re, 'Hello world'): if re.search(phone_re, 'Hello world'):
print("No match; this won't print") print("No match; this won't print")
...@@ -81,11 +81,11 @@ if re.search(phone_re, 'Hello world'): ...@@ -81,11 +81,11 @@ if re.search(phone_re, 'Hello world'):
另一个常用的方法`re.match(pattern, string)`的行为与`re.search`相同,但只检查`string`开头的匹配项,而不是字符串中任何位置的匹配项。 另一个常用的方法`re.match(pattern, string)`的行为与`re.search`相同,但只检查`string`开头的匹配项,而不是字符串中任何位置的匹配项。
## `re.findall`[¶](#re.findall) #### `re.findall`[](#re.findall)
我们使用`re.findall(pattern, string)`提取与 regex 匹配的子字符串。此方法返回`string`中所有匹配项的列表。 我们使用`re.findall(pattern, string)`提取与 regex 匹配的子字符串。此方法返回`string`中所有匹配项的列表。
``` ```python
gmail_re = r'[a-zA-Z0-9]+@gmail\.com' gmail_re = r'[a-zA-Z0-9]+@gmail\.com'
text = ''' text = '''
From: email1@gmail.com From: email1@gmail.com
...@@ -99,13 +99,13 @@ re.findall(gmail_re, text) ...@@ -99,13 +99,13 @@ re.findall(gmail_re, text)
['email1@gmail.com', 'email3@gmail.com'] ['email1@gmail.com', 'email3@gmail.com']
``` ```
## regex 组[¶](#Regex-Groups) ## Regex 组[](#Regex-Groups)
使用**regex groups**,我们通过将子模式包装在括号`( )`中指定要从 regex 提取的子模式。当 regex 包含 regex 组时,`re.findall`返回包含子模式内容的元组列表。 使用**regex 组**,我们通过将子模式括在括号`( )`中指定要从 regex 提取的子模式。当 regex 包含 regex 组时,`re.findall`返回包含子模式内容的元组列表。
例如,以下熟悉的 regex 从字符串中提取电话号码: 例如,以下是我们熟悉的用 regex 从字符串中提取电话号码:
``` ```python
phone_re = r"[0-9]{3}-[0-9]{3}-[0-9]{4}" phone_re = r"[0-9]{3}-[0-9]{3}-[0-9]{4}"
text = "Sam's number is 382-384-3840 and Mary's is 123-456-7890." text = "Sam's number is 382-384-3840 and Mary's is 123-456-7890."
re.findall(phone_re, text) re.findall(phone_re, text)
...@@ -130,15 +130,15 @@ re.findall(phone_re, text) ...@@ -130,15 +130,15 @@ re.findall(phone_re, text)
[('382', '384', '3840'), ('123', '456', '7890')] [('382', '384', '3840'), ('123', '456', '7890')]
``` ```
正如所承诺的那样,`re.findall`返回包含匹配电话号码的各个组的元组列表。 正如所承诺的那样,`re.findall`返回包含匹配电话号码的各个组成部分的元组列表。
## `re.sub`[¶](#re.sub) #### `re.sub`[](#re.sub)
`re.sub(pattern, replacement, string)`提供的`string`中的`replacement`替换所有出现的`pattern`。此方法的行为类似于 python 字符串方法`str.sub`,但使用 regex 来匹配模式。 `re.sub(pattern, replacement, string)``replacement`替换`string`所有出现的`pattern`。此方法的行为类似于 python 字符串方法`str.sub`,但使用 regex 来匹配模式。
在下面的代码中,我们通过用破折号替换日期分隔符来将日期更改为通用格式。 在下面的代码中,我们通过用破折号替换日期分隔符来将日期更改为通用格式。
``` ```python
messy_dates = '03/12/2018, 03.13.18, 03/14/2018, 03:15:2018' messy_dates = '03/12/2018, 03.13.18, 03/14/2018, 03:15:2018'
regex = r'[/.:]' regex = r'[/.:]'
re.sub(regex, '-', messy_dates) re.sub(regex, '-', messy_dates)
...@@ -149,13 +149,13 @@ re.sub(regex, '-', messy_dates) ...@@ -149,13 +149,13 @@ re.sub(regex, '-', messy_dates)
'03-12-2018, 03-13-18, 03-14-2018, 03-15-2018' '03-12-2018, 03-13-18, 03-14-2018, 03-15-2018'
``` ```
## `re.split`[](#re.split) ## `re.split`[](#re.split)
每次出现 regex`pattern`时,`re.split(pattern, string)`分割输入`string`。此方法的行为类似于 python 字符串方法`str.split`,但使用 regex 进行拆分 `re.split(pattern, string)`在每次出现regex `pattern`时分割输入的`string`。此方法的行为类似于 python 字符串方法`str.split`,但使用 regex 进行分割
在下面的代码中,我们使用`re.split`章节名称从它们的页码中拆分为一本书的目录 在下面的代码中,我们使用`re.split`一本书目录的章节名称和它们的页码分开
``` ```python
toc = ''' toc = '''
PLAYING PILGRIMS============3 PLAYING PILGRIMS============3
A MERRY CHRISTMAS===========13 A MERRY CHRISTMAS===========13
...@@ -178,7 +178,7 @@ lines ...@@ -178,7 +178,7 @@ lines
'BEING NEIGHBORLY============76'] 'BEING NEIGHBORLY============76']
``` ```
``` ```python
# Then, split into chapter title and page number # Then, split into chapter title and page number
split_re = r'=+' # Matches any sequence of = characters split_re = r'=+' # Matches any sequence of = characters
[re.split(split_re, line) for line in lines] [re.split(split_re, line) for line in lines]
...@@ -193,13 +193,13 @@ split_re = r'=+' # Matches any sequence of = characters ...@@ -193,13 +193,13 @@ split_re = r'=+' # Matches any sequence of = characters
['BEING NEIGHBORLY', '76']] ['BEING NEIGHBORLY', '76']]
``` ```
## regex 和 pandas[?](#Regex-and-pandas) ## Regex 和 pandas[](#Regex-and-pandas)
回想一下`pandas`系列对象有一个`.str`属性,它支持使用 python 字符串方法进行字符串操作。很方便,`.str`属性还支持来自`re`模块的一些函数。我们在`pandas`中演示了 regex 的基本用法,将完整的方法列表留给[有关字符串方法](https://pandas.pydata.org/pandas-docs/stable/text.html)`pandas`文档 回想一下`pandas` Series对象有一个`.str`属性,它支持使用 python 字符串方法进行字符串操作。很方便的是,`.str`属性还支持一些`re`模块的函数。我们演示了regex在`pandas`中的基本用法,完整的方法列表在[有关字符串方法的`pandas`文档](https://pandas.pydata.org/pandas-docs/stable/text.html)
我们在下面的数据框中存储了小说《小女人》(HTG1)的前五句话的文本。我们可以使用`pandas`提供的字符串方法来提取每个句子中的口语对话。 我们在下面的DataFrame中保存了小说《小女人》(*Little Women*)前五句话的文本。我们可以使用`pandas`提供的字符串方法来提取每个句子中的口语对话。
``` ```python
# HIDDEN # HIDDEN
text = ''' text = '''
"Christmas won't be Christmas without any presents," grumbled Jo, lying on the rug. "Christmas won't be Christmas without any presents," grumbled Jo, lying on the rug.
...@@ -219,22 +219,17 @@ little ...@@ -219,22 +219,17 @@ little
``` ```
| | 句子 | | | sentences |
| --- | --- | | --- | ---: |
| 零 | “没有压力,圣诞节不会是圣诞节…… | | 0 | "Christmas won't be Christmas without any pres... |
| --- | --- | | 1 | "It's so dreadful to be poor!" sighed Meg, loo... |
| 1 个 | “穷真可怕!”梅格叹了口气,卢…… | | 2 | "I don't think it's fair for some girls to hav... |
| --- | --- | | 3 | "We've got Father and Mother, and each other,"... |
| 二 | “我认为有些女孩不公平地… | | 4 | The four young faces on which the firelight sh... |
| --- | --- |
| 三 | “我们有爸爸妈妈,还有彼此,”… |
| --- | --- |
| 四 | 四张年轻的脸上有火光… |
| --- | --- |
由于口语对话位于双引号内,因此我们创建一个 regex,它捕获双引号、除双引号外的任何字符序列和右引号。 由于口语对话位于双引号内,因此我们创建一个 regex,它捕获左双引号、除双引号外的任何字符序列和右双引号。
``` ```python
quote_re = r'"[^"]+"' quote_re = r'"[^"]+"'
little['sentences'].str.findall(quote_re) little['sentences'].str.findall(quote_re)
...@@ -249,9 +244,9 @@ little['sentences'].str.findall(quote_re) ...@@ -249,9 +244,9 @@ little['sentences'].str.findall(quote_re)
Name: sentences, dtype: object Name: sentences, dtype: object
``` ```
由于`Series.str.findall`方法返回匹配项列表,`pandas`还提供`Series.str.extract``Series.str.extractall`方法将匹配项提取到序列或数据帧中。这些方法要求 regex 至少包含一个 regex 组。 由于`Series.str.findall`方法返回匹配项列表,`pandas`还提供`Series.str.extract``Series.str.extractall`方法将匹配项提取到Series或DataFrame中。这些方法要求 regex 至少包含一个 regex 组。
``` ```python
# Extract text within double quotes # Extract text within double quotes
quote_re = r'"([^"]+)"' quote_re = r'"([^"]+)"'
spoken = little['sentences'].str.extract(quote_re) spoken = little['sentences'].str.extract(quote_re)
...@@ -268,30 +263,25 @@ spoken ...@@ -268,30 +263,25 @@ spoken
Name: sentences, dtype: object Name: sentences, dtype: object
``` ```
我们可以将此系列添加为`little`数据帧的列: 我们可以将此序列添加为`little`DataFrame的列:
``` ```python
little['dialog'] = spoken little['dialog'] = spoken
little little
``` ```
| | sentences | 对话 | | | sentences | dialog |
| --- | --- | --- | | --- | ---: | ---: |
| 0 | "Christmas won't be Christmas without any pres... | 圣诞节不会是没有任何预设的圣诞节… | | 0 | "Christmas won't be Christmas without any pres... | Christmas won't be Christmas without any prese... |
| --- | --- | --- | | 1 | "It's so dreadful to be poor!" sighed Meg, loo... | It's so dreadful to be poor! |
| 1 | "It's so dreadful to be poor!" sighed Meg, loo... | 穷真可怕! | | 2 | "I don't think it's fair for some girls to hav... | I don't think it's fair for some girls to have... |
| --- | --- | --- | | 3 | "We've got Father and Mother, and each other,"... | We've got Father and Mother, and each other, |
| 2 | "I don't think it's fair for some girls to hav... | 我觉得有些女孩有… | | 4 | The four young faces on which the firelight sh... | We haven't got Father, and shall not have him ... |
| --- | --- | --- |
| 3 | "We've got Father and Mother, and each other,"... | 我们有父亲和母亲,还有彼此, |
| --- | --- | --- |
| 4 | The four young faces on which the firelight sh... | 我们没有父亲,也不会有他…… |
| --- | --- | --- |
我们可以通过打印原始和提取的文本来确认字符串操作在数据框中的最后一句话中的行为是否如预期 我们可以通过打印原始文本和提取文本来确认字符串操作在DataFrame中的最后一句话上是否如预期执行
``` ```python
print(little.loc[4, 'sentences']) print(little.loc[4, 'sentences'])
``` ```
...@@ -301,7 +291,7 @@ The four young faces on which the firelight shone brightened at the cheerful wor ...@@ -301,7 +291,7 @@ The four young faces on which the firelight shone brightened at the cheerful wor
``` ```
``` ```python
print(little.loc[4, 'dialog']) print(little.loc[4, 'dialog'])
``` ```
...@@ -311,10 +301,10 @@ We haven't got Father, and shall not have him for a long time. ...@@ -311,10 +301,10 @@ We haven't got Father, and shall not have him for a long time.
``` ```
## 摘要[](#Summary) ## 摘要[](#Summary)
python 中的`re`模块提供了一组使用正则表达式操作文本的有用方法。在处理数据帧时,我们经常使用在`pandas`中实现的类似的字符串操作方法。 python 中的`re`模块提供了一组使用正则表达式操作文本的实用方法。在处理DataFrame时,我们经常使用`pandas`中实现的类似的字符串操作方法。
有关`re`模块的完整文档,请参阅[https://docs.python.org/3/library/re.html](https://docs.python.org/3/library/re.html) 有关`re`模块的完整文档,请参阅[https://docs.python.org/3/library/re.html](https://docs.python.org/3/library/re.html)
有关`pandas`字符串方法的完整文档,请参阅[https://pandas.pydata.org/pandas-docs/stable/text.html](https://pandas.pydata.org/pandas-docs/stable/text.html) 有关`pandas`字符串方法的完整文档,请参阅[https://pandas.pydata.org/pandas-docs/stable/text.html](https://pandas.pydata.org/pandas-docs/stable/text.html)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册