字符串与正则
字符串
python 中,字符串(str)是一种不可变的序列结构。
字符串创建
定义字符串的方法有以下几种:
-
单引号、双引号
在 python 中,单双引号是完全等价的,在某些语言中,可能会区分字符和字符串,但在 python 中,字符就是长度为 1 的字符串。
1
2str1 = "Hello, world!"
str2 = '114.514' -
三引号
使用三个双引号或单引号可以创建多行字符串。三引号允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符。1
2
3mstr = """line1,
line2,
line3!"""
字符串转义
使用反斜杠可以转义字符。
转义字符 | 描述 | ASCII码 |
---|---|---|
\’ | 单引号 | 39 |
\" | 双引号 | 34 |
\\ | 反斜杠 | 92 |
\n | 换行 | 10 |
\t | 制表符 | 9 |
1 |
|
原始字符串
原始字符串使用一个前缀"r"来标识。原始字符串与普通字符串的区别在于,它不会对反斜杠进行转义,因此可以用来表示含有反斜杠的字符串。例如:
1 |
|
字符串格式化
format
是字符串的一个方法,用来格式化字符串。
format()
方法在字符串中添加变量时使用花括号{}作为占位符,并使用format()
将变量传递给它来替换占位符。
1 |
|
你可能见过这种格式化字符串方法:
1 |
|
这种写法已经过时了。请使用字符串的 format
方法。
格式化字符串
f-string
方法是从 Python 3.6 版本开始引入的,它是一种更简洁,快速的格式化字符串的方法。 它使用花括号{}作为占位符,并直接在变量前加上字母f。
1 |
|
正则
正则表达式是一种用来描述文本模式的语法规则。它在计算机科学中被广泛应用于文本处理,例如验证、搜索、替换文本等。正则表达式可在基本上所有语言中通用(如python,C++,JavaScript)。
在B站中,你也可以通过正则来快速屏蔽一系列弹幕。
在 python 中,正则表达式由内置库 re
实现。在 re
库中,常用的有四个函数:re.match
,re.search
,re.findall
,re.sub
。
引入
考虑如下场景:你是某网站前端,需要识别一个手机号是否合法。
一个手机号被称为合法的,当且仅当
- 由 11 个数字组成;
- 开头必须是数字 1;
- 第二位必须是 3-9 的数字。
精通 python 的你马上写出了如下代码
1 |
|
看起来很美好,但是当规则变得复杂起来后(如识别一个合法邮箱地址),这样的代码就似乎有些繁琐了。
事实上,如果用正则表达式来写刚才的代码,仅仅需要一行:
1 |
|
我们来学习如何编写正则表达式(如上代码中 ^1[3-9]\d{9}$
)。
正则表达式的编写
一个简单的正则表达式可以仅仅由字符组成。例如,hello
。
该表达式只会匹配 hello
。
字符集
字符集是一系列字符的集合。
表达式 | 含义 |
---|---|
[xyz] [a-c] |
匹配包含在方括号中的任何字符。你可以使用连字符指定字符范围,但如果连字符出现在方括号中的第一个或最后一个字符,则将其视为字面连字符,作为普通字符包含在字符类中。 例如, [abcd-] 和 [-abcd] 匹配brisket 中的b 、chop 中的c 和non-profit 中的- (连字符);[0-9] 匹配所有数字,[a-zA-Z0-9] 匹配数字和字母。 |
[^xyz] [^a-c] |
匹配任何未包含在方括号中的字符 例如, [^a-z] 匹配 hello1 中的 1 |
. |
匹配任何字符,在[] 内,点失去了它的特殊意义,并与文字点匹配。 |
\d |
匹配任何数字,相当于[0-9] 。 |
\w |
匹配基本拉丁字母中的任何字母数字字符,包括下划线,相当于[A-Za-z0-9_] 。 |
\ |
转义字符。例如,\\ 匹配反斜杠,\* 匹配星号。 |
x|y |
析取:匹配 x 或 y 。例如,green|red 匹配 green apple 中的 green 和 red apple 中的 red 。 |
量词
量词表示要匹配的字符或表达式的数量。
表达式 | 含义 |
---|---|
x* |
将前面的项“x”匹配 0 次或更多次。 例如, hello* 可以匹配 hello ,helloooooooo ,hell 。 |
x+ |
将前面的项“x”匹配 1 次或更多次。 例如, hello+ 可以匹配 hello ,helloooooooo ,但不能匹配 hell 。 |
x? |
将前面的项“x”匹配 0 或 1 次。 例如, hello? 可以匹配 hello ,hell 。 |
x{n} |
与前一项“x”的 n 次匹配 例如, hello{5} 只能匹配 hellooooo 。 |
x{n,} |
与前一项“x”至少匹配“n”次。 例如, hello{5,} 可以匹配 hellooooo ,helloooooo ,helloooooooo 。 |
x{n,m} |
与前一项“x”匹配“n”到“m”次 例如, hello{5,6} 只能匹配 hellooooo ,helloooooo 。 |
x*? x+? x?? x{n}? x{n,}? x{n,m}? |
默认情况下,像 * 和 + 这样的量词是“贪婪的”,这意味着它们试图匹配尽可能多的字符串。?量词后面的字符使量词“非贪婪”:意思是它一旦找到匹配就会停止。例如,给定一个字符串 some <foo> <bar> new </bar> </foo> thing :<.*> 会匹配 <foo> <bar> new </bar> </foo> ;<.*?> 只会匹配 <foo> 。 |
断言
断言匹配表达式的边界(简略介绍两个最常用断言)。
表达式 | 含义 |
---|---|
^ |
匹配开头。例如 ^a 匹配 apple 中的 a ,不匹配 say 中的 a 。 |
$ |
匹配开头。例如 a$ 匹配 ga 中的 a ,不匹配 say 中的 a 。 |
字符串验证
想要判断某个字符串是否符合指定规则,可以使用 re.match
函数或 re.search
。
match
函数从开头开始匹配,search
函数可以从中间开始匹配。
它们都返回一个匹配对象 re.Match
。若未匹配,返回 None
。
例如,以下可以判断邮箱地址是否合法:
1 |
|
- ^表示匹配字符串的开始位置
[a-zA-Z0-9._%+-]+
表示匹配至少一个字母、数字、下划线、句点、百分号、加号或减号@
表示匹配@
符号[a-zA-Z0-9.-]+
表示匹配至少一个字母、数字、句点或连字符\.
表示匹配一个句点[a-zA-Z]{2,}
表示匹配至少两个字母$
表示匹配字符串的结尾位置
字符串搜索
re.search
有一段文本
1 |
|
你想提取出中国在2018年世界GDP的排位和具体值。
现在问题不是验证,而是提取信息。需要用到另一个功能——捕获组。一个捕获组用 ()
定义。
1 |
|
re.search
返回 re.Match
对象,其中 groups
方法返回一个所有捕获组的元组。
还可以使用 group(1)
返回第一个捕获组,以此类推。
re.findall
有一天,你突发奇想,想要找到一篇文章里所有人说的话。
1 |
|
你马上编写了如下正则表达式 “.+?”
,用来匹配所有引号内的内容。
1 |
|
我们看到,返回了一个字符串的列表,就是每次匹配的内容。
这时候,你想:能不能不要引号?用捕获组即可,若pattern中只有一个捕获组,会返回捕获组中内容的列表。
如下:
1 |
|
可以看到,确实只返回了捕获组里的内容。
如果一个表达式里有超过一个捕获组,则会返回一个字符串元组的列表。
1 |
|
这样就可以同时匹配话和人的名字。
字符串替换
你又突发奇想,想要把引号改成书名号,可以使用 re.sub
编写代码。
1 |
|
这个表示对所有满足 “(.*?)”
的内容,都替换成第二个参数。其中 \g<1>
表示第一个捕获组。
输出:
1 |
|
练习
网页处理
这是一篇注音后的荷塘月色节选。要求分析网页结构,使用爬虫,将注音转化为纯文本形式。
即得到:
月光(yuè guāng)如流水(liú shuǐ)一般,静静地泻在这一片叶子和花上。薄薄的青雾浮起在荷塘里。叶子和花仿佛在牛乳(niú rǔ)中洗过一样;又像笼着轻纱的梦。虽然是满月(yuè),天上却有一层淡淡的云,所以不能朗照;但我以为这恰是到了好处——酣眠固不可少,小睡也别有风味的。月光是隔了树照过来的,高处丛生(cóng shēng)的灌木,落下参差的斑驳(bān bó)的黑影,峭(qiào)楞楞如鬼(guǐ)一般;弯弯(wān wān)的杨柳(yáng liǔ)的稀疏(xī shū)的倩影,却又像是画在荷叶上。塘中的月色并不均匀;但光与影有着和谐的旋律,如梵婀玲(fàn é líng)上奏着的名曲。
知识库:
html中,ruby标签可为文字注音。rt标签内为文字的发音。
1 |
|
歌词处理
残酷な天使のテーゼ(残酷天使的行动纲领) - 高橋洋子 - 单曲 - 网易云音乐
你想获取这首歌的歌词。你通过爬虫(已帮你写好)从该网页上获取了歌词的内容,接下来要进行处理。
1 |
|
请自己运行代码,并分析返回的两个字符串。然后编写代码,处理数据,要求能得到如下几个变量。
1 |
|